反应:为什么道具改变时子组件不更新

JavaScript

Eva梅村村

2020-03-12

为什么在以下伪代码示例中,当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>
  }
}

即使forceUpdate()在修改Container中的值后调用,Child仍会显示旧值。

第995篇《反应:为什么道具改变时子组件不更新》来自Winter(https://github.com/aiyld/aiyld.github.io)的站点

9个回答
GOItachi老丝 2020.03.12

如果不保持任何状态而只是渲染道具然后从父级调用它,则应该将Child用作功能组件。替代方法是,可以将钩子与功能组件(useState)一起使用,这将导致无状态组件重新呈现。

同样,您不应更改道具,因为它们是不可变的。维护组件的状态。

Child = ({bar}) => (bar);
番长理查德 2020.03.12

我遇到了同样的问题。我有一个Tooltip正在接收showTooltip道具组件,我正在Parent根据if条件组件上进行更新,它正在组件中进行更新,Parent但是Tooltip组件未渲染。

const Parent = () => {
   let showTooltip = false;
   if(....){ showTooltip = true; }
   return(
      <Tooltip showTooltip={showTooltip}></Tooltip>
   )
}

我正在做的错误是声明showTooltip为let。

我意识到自己做错了我违反了渲染工作原理的工作,用钩子代替了工作。

const [showTooltip, setShowTooltip] =  React.useState<boolean>(false);
达蒙十三 2020.03.12

确认后,添加密钥即可。我浏览了文档以尝试并了解原因。

在创建子组件时,React希望高效。如果它与另一个子组件相同,则不会渲染新组件,这会使页面加载更快。

添加一个键会强制React渲染一个新组件,从而为该新组件重置State。

https://reactjs.org/docs/reconciliation.html#recursing-on-children

阿飞GO 2020.03.12

我有同样的问题。这是我的解决方案,我不确定这是否是个好习惯,如果不是,请告诉我:

state = {
  value: this.props.value
};

componentDidUpdate(prevProps) {
  if(prevProps.value !== this.props.value) {
    this.setState({value: this.props.value});
  }
}

UPD:现在您可以使用React Hooks执行相同的操作:(仅当component是一个函数时)

const [value, setValue] = useState(propName);
// This will launch only if propName value has chaged.
useEffect(() => { setValue(propName) }, [propName]);
小小Gil 2020.03.12

根据React哲学的组成部分,无法更改其道具。它们应该从父级那里接收,并且应该是不变的。只有父母可以改变孩子的道具。

关于状态与道具的很好的解释

另外,请阅读此线程为什么我不能在react.js中更新道具?

逆天前端 2020.03.12

更新子项以使其属性“键”等于名称。每次更改键时,组件都会重新渲染。

Child {
  render() {
    return <div key={this.props.bar}>{this.props.bar}</div>
  }
}
梅Jim 2020.03.12

您应该使用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>
        }
    }
}

您的代码似乎无效。我无法测试此代码。

梅伽罗 2020.03.12

使用setState函数。所以你可以做

       this.setState({this.state.foo.bar:123}) 

在handle事件方法中。

状态一旦更新,将触发更改,然后进行重新渲染。

StafanMandy 2020.03.12

因为如果父项的props发生变化,但是STATE的状态发生变化,则子项不会重新呈现:)

您显示的是这样的:https : //facebook.github.io/react/tips/communicate-between-components.html

它将通过道具将数据从父级传递到子级,但是那里没有重新渲染逻辑。

您需要为父级设置一些状态,然后在父级更改状态下重新渲染子级。这可能会有所帮助。 https://facebook.github.io/react/tips/expose-component-functions.html

问题类别

JavaScript Ckeditor Python Webpack TypeScript Vue.js React.js ExpressJS KoaJS CSS Node.js HTML Django 单元测试 PHP Asp.net jQuery Bootstrap IOS Android