【问题标题】:React Child is updating Parent State when manipulating the props in child. UnwantedReact Child 在操作 child 中的 props 时正在更新 Parent State。不需要的
【发布时间】:2021-05-09 10:19:57
【问题描述】:

以下代码位于https://codesandbox.io/s/child-updating-parent-dont-want-pfdxd 我面临的问题是,当我对子组件(page2)进行排序时,它还会更新父组件(App)的状态。我想避免状态更新,因为其他子组件(第 1 页)应该显示未排序的数据。我想过在 App.js 上有两个具有相同数据(两个名称和两个数字)的状态。然后为第 1 页使用一组状态(名称和数字),为第 2 页使用另一组。这似乎是多余和不必要的,但我不确定在第 2 页排序时如何避免状态更新。有没有办法避免在子组件中操作数据时的状态更新?

/*Parent*/  
    class App extends React.Component {
      constructor() {
        super();
        this.state = {
          numbers: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
          names: ["john", "sally", "bill", "rebecca"]
        };
      }
      render() {
        const { numbers, names } = this.state;
        return (
          <Router>
            <div className="App">
              <Header />
              <Switch>
                <Route
                  path="/page1"
                  exact
                  render={(routeProps) => (
                    <Page1 digits={numbers} people={names} {...routeProps} />
                  )}
                />
                <Route
                  path="/page2"
                  exact
                  render={(routeProps) => (
                    <Page2 digits={numbers} people={names} {...routeProps} />
                  )}
                />
              </Switch>
            </div>
          </Router>
        );
      }
    }
    export default App;

这是第一个接收道具的组件

/*child 1*/
const page1 = ({ people, digits }) => {
  return (
    <div>
      <h1>
        Number Should Be "1" And Name Should Be "john" On This Page Regardless
        Of Sort On Page 2
      </h1>

      <p>Number: {digits[0]}</p>
      <p>Name: {people[0]}</p>
    </div>
  );
};
export default page1;

这是接收道具的第二个组件

/*child 2*/

    const Page2 = ({ people, digits }) => {
      /* when uncommented the sort will also change state on App.js --- 
      I want state on App.js to remain in original state aft sorting*/
    
      /* --- UNCOMMENT BELOW TO SORT --- */
    
      /*people.sort((a, b) => b.toLowerCase().localeCompare(a.toLowerCase()));
      digits.sort((a,b)=>b-a)*/
    
      return (
        <div>
          <h1>
            Number Should Be "10" And Name Should Be "sally" On This Page When Sort
            Is Uncommented
          </h1>
          <p>Number: {digits[0]}</p>
          <p>Name: {people[0]}</p>
        </div>
      );
    };
    export default Page2;

【问题讨论】:

  • 在 react 中的 props 是不可变的。您正在使用数组 sort 方法改变道具。 sort 不会返回一个新数组,它会改变现有数组,这就是你的状态正在改变的原因。
  • 我需要将排序设置为变量吗?关于如何避免的建议?

标签: reactjs react-props react-state


【解决方案1】:

在 Javascript 中,sort 方法执行就地排序。因此,当您执行people.sort 时,实际上最终会修改传递的people 属性。由于数组是通过引用传递的,people 的每个其他引用都会显示新的排序值。

要解决此问题,您应该更改传递的道具的本地副本以防止出现此类意外结果。

const Page2 = ({ people, digits }) => {

  const sortedPeople = [...people].sort((a, b) => b.toLowerCase().localeCompare(a.toLowerCase()))
  
  const sortedDigits = [...digits].sort((a,b)=>b-a);

  return (
    <div>
      <h1>
        Number Should Be "10" And Name Should Be "sally" On This Page When Sort
        Is Uncommented
      </h1>
      <p>Number: {sortedDigits[0]}</p>
      <p>Name: {sortedPeople[0]}</p>
    </div>
  );
};
export default Page2;

为了进一步解释上述方法中发生的事情,

我们现在不是直接改变 prop,而是创建数组的副本,在本例中是 peopledigits,通过使用像 [...people] 这样的 ES6 扩展运算符并在这个新副本上排序。

const sortedPeople = [...people].sort((a, b) => b.toLowerCase().localeCompare(a.toLowerCase()))

附言。你也可以通过Array.from(people)people.slice() 来达到同样的效果。

请记住,您可以通过使用 useMemo 钩子在 React 中进一步优化它的渲染性能并执行类似的操作

const sortedPeople = useMemo(() => [...people].sort((a, b) => b.toLowerCase().localeCompare(a.toLowerCase())), [people]);

【讨论】:

  • 这是一个很好的答案,适用于我的情况。非常感谢!
  • 太棒了。如果它对您有所帮助,也请投票支持此答案,以便此答案可以帮助更多面临类似代码问题的人。
  • 我投了赞成票。它只是没有出现,因为我没有 15 声望。再次感谢您的帮助!
猜你喜欢
  • 2023-03-06
  • 2020-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多