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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 22:00:11  来源:igfitidea点击:

React: why child component doesn't update when prop changes

javascripthtmlreactjs

提问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 setStatefunction. 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 functionsand 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 Tooltipcomponent that was receiving showTooltipprop, that I was updating on Parentcomponent based on an ifcondition, it was getting updated in Parentcomponent but Tooltipcomponent 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 showTooltipas 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);