Javascript React:为什么当 prop 更改时子组件不更新
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/38892672/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
React: why child component doesn't update when prop changes
提问by Tuomas Toivonen
Why in the following pseudo-code example Child doesn't re-render when Container changes foo.bar?
为什么在下面的伪代码示例中,当 Container 更改 foo.bar 时,Child 不会重新渲染?
Container {
handleEvent() {
this.props.foo.bar = 123
},
render() {
return <Child bar={this.props.foo.bar} />
}
Child {
render() {
return <div>{this.props.bar}</div>
}
}
Even if I call forceUpdate()
after modifying the value in Container, Child still shows the old value.
即使我forceUpdate()
在修改Container中的值后调用,Child仍然显示旧值。
回答by Fran?ois Richard
Because children do not rerender if the props of the parent change, but if its STATE changes :)
因为如果父级的 props 发生变化,子级不会重新渲染,但是如果它的 STATE 发生变化:)
What you are showing is this: https://facebook.github.io/react/tips/communicate-between-components.html
你展示的是这个:https: //facebook.github.io/react/tips/communicate-between-components.html
It will pass data from parent to child through props but there is no rerender logic there.
它将通过 props 将数据从父级传递给子级,但那里没有重新渲染逻辑。
You need to set some state to the parent then rerender the child on parent change state. This could help. https://facebook.github.io/react/tips/expose-component-functions.html
您需要为父级设置一些状态,然后在父级更改状态时重新渲染子级。这可能会有所帮助。 https://facebook.github.io/react/tips/expose-component-functions.html
回答by polina-c
Update child to have attribute 'key' equal to name. The component will re-render every time the key changes.
更新孩子的属性“key”等于名称。每次密钥更改时,组件都会重新渲染。
Child {
render() {
return <div key={this.props.bar}>{this.props.bar}</div>
}
}
回答by petrichor
I had the same problem. This is my solution, I'm not sure that is the good practice, tell me if not:
我有同样的问题。这是我的解决方案,我不确定这是好的做法,如果不是,请告诉我:
state = {
value: this.props.value
};
componentDidUpdate(prevProps) {
if(prevProps.value !== this.props.value) {
this.setState({value: this.props.value});
}
}
UPD: Now you can do the same thing using React Hooks: (only if component is a function)
UPD:现在你可以使用 React Hooks 做同样的事情:(仅当组件是一个函数时)
const [value, setValue] = useState(propName);
// This will launch only if propName value has chaged.
useEffect(() => { setValue(propName) }, [propName]);
回答by Sujan Thakare
According to React philosophy component can't change its props. they should be received from the parent and should be immutable. Only parent can change the props of its children.
根据 React 哲学,组件不能改变它的 props。它们应该从父级接收并且应该是不可变的。只有父级可以更改其子级的道具。
nice explanation on state vs props
关于状态与道具的很好解释
also, read this thread Why can't I update props in react.js?
另外,请阅读此线程为什么我不能在 react.js 中更新道具?
回答by JamesYin
You should use setState
function. If not, state won't save your change, no matter how you use forceUpdate.
你应该使用setState
函数。如果没有,无论您如何使用 forceUpdate,state 都不会保存您的更改。
Container {
handleEvent= () => { // use arrow function
//this.props.foo.bar = 123
//You should use setState to set value like this:
this.setState({foo: {bar: 123}});
};
render() {
return <Child bar={this.state.foo.bar} />
}
Child {
render() {
return <div>{this.props.bar}</div>
}
}
}
Your code seems not valid. I can not test this code.
您的代码似乎无效。我无法测试此代码。
回答by tjr226
Confirmed, adding a Key works. I went through the docs to try and understand why.
确认,添加 Key 有效。我浏览了文档以尝试了解原因。
React wants to be efficient when creating child components. It won't render a new component if it's the same as another child, which makes the page load faster.
React 希望在创建子组件时高效。如果它与另一个子组件相同,则不会呈现新组件,这会使页面加载速度更快。
Adding a Key forces React to render a new component, thus resetting State for that new component.
添加一个 Key 会强制 React 渲染一个新组件,从而重置该新组件的 State。
https://reactjs.org/docs/reconciliation.html#recursing-on-children
https://reactjs.org/docs/reconciliation.html#recursing-on-children
回答by Indraneel Bende
Use the setState function. So you could do
使用 setState 函数。所以你可以这样做
this.setState({this.state.foo.bar:123})
inside the handle event method.
在句柄事件方法中。
Once, the state is updated, it will trigger changes, and re-render will take place.
一旦状态被更新,它就会触发变化,并且会发生重新渲染。
回答by Nelles
When create React components from functions
and useState
.
当从functions
和创建 React 组件时useState
。
const [drawerState, setDrawerState] = useState(false);
const toggleDrawer = () => {
// attempting to trigger re-render
setDrawerState(!drawerState);
};
This does notwork
这确实不工作
<Drawer
drawerState={drawerState}
toggleDrawer={toggleDrawer}
/>
This does work(adding key)
这确实有效(添加密钥)
<Drawer
drawerState={drawerState}
key={drawerState}
toggleDrawer={toggleDrawer}
/>
回答by Rajesh Nasit
define changed props in mapStateToProps of connect method in child component.
在子组件的 connect 方法的 mapStateToProps 中定义更改的道具。
function mapStateToProps(state) {
return {
chanelList: state.messaging.chanelList,
};
}
export default connect(mapStateToProps)(ChannelItem);
In my case, channelList's channel is updated so I added chanelList in mapStateToProps
就我而言,channelList 的频道已更新,因此我在 mapStateToProps 中添加了 chanelList
回答by Divyanshu Rawat
I was encountering the same problem.
I had a Tooltip
component that was receiving showTooltip
prop, that I was updating on Parent
component based on an if
condition, it was getting updated in Parent
component but Tooltip
component was not rendering.
我遇到了同样的问题。我有一个Tooltip
正在接收showTooltip
道具的组件,我正在Parent
根据if
条件更新Parent
组件,它正在组件中更新但Tooltip
组件没有呈现。
const Parent = () => {
let showTooltip = false;
if(....){ showTooltip = true; }
return(
<Tooltip showTooltip={showTooltip}></Tooltip>
)
}
The mistake I was doing is to declare showTooltip
as a let.
我做的错误是声明showTooltip
为 let 。
I realized what I was doing wrong I was violating the principles of how rendering works, Replacing it with hooks did the job.
我意识到我做错了什么,我违反了渲染工作原理,用钩子代替它完成了这项工作。
const [showTooltip, setShowTooltip] = React.useState<boolean>(false);