当子组件更新时反应更新父级

时间:2021-01-29 00:58:50

标签: javascript reactjs react-native react-hooks parent

为什么父组件总是显示比子组件少1? 第一次更新后不会重新渲染。

export const Parent = (props) => {
  const [count, setCount] = React.useState(0);
  return (
    <View>
      <Text>Parent: {count}</Text>
      <Child updateCount={setCount} />
    </View>
  );
};

const Child = (props) => {
  const [count, setCount] = React.useState(0);

  const updateCount = () => {
    setCount((count) => count + 1);
    return props.updateCount(count);
  };
  return (
    <View>
      <Text>Child: {count}</Text>
      <Button title="add" onPress={updateCount} />
    </View>
  );
};

4 个答案:

答案 0 :(得分:2)

主要问题是您希望 setCount 立即发生,尽管它是一个异步操作。问题出在以下代码中的 <Child /> 组件中:

const updateCount = () => {
    setCount((count) => count + 1)
    return props.updateCount(count)
}

从技术上讲,您希望 count 被更新并传递给 props.updatedCount,同时它仍然具有以前的值。

这也与问题无关,但您实际上并不需要从更新状态的函数返回,因此只需删除 return 关键字。


解决这个问题有多种选择。

  1. 在代码中仍然使用分离状态:

只需以与另一个 props.updateCount 完全相同的方式调用 setState 为:

const updateCount = () => {
  setCount((count) => count + 1)
  props.updateCount((count) => count + 1)
}
  1. <Parent /> 中保持一种状态并通过 props 向下传递:

所以主要的解决方案是:

export const Parent = (props) => {
  const [count, setCount] = React.useState(0);
  return (
    <View>
      <Text>Parent: {count}</Text>
      {/* passed here count as well: */}
      <Child updateCount={setCount} count={count} />
    </View>
  );
};

// destructure here updateCount and count
const Child = ({ updateCount, count }) => {
  return (
    <View>
      {/* using here count from parent */}
      <Text>Child: {count}</Text>
      {/* calling here updateCount from the props as: */}
      <Button title="add" onPress={() => updateCount((count) => count + 1} />
    </View>
  );
};
  1. 第三种选择是使用Context API

通过使用 Context,您可以执行以下操作,参见文档:

<块引用>

Context 提供了一种通过组件树传递数据的方法,而无需在每个级别手动向下传递 props。

通常,一旦我们拥有比当前更复杂的组件树,我就喜欢使用 Context。所以我建议保留一种状态选项。

答案 1 :(得分:1)

@norbital 的 N°2 解决方案很有魅力,就我而言,它是类组件而不是功能组件。在这里只发布一个适合类组件的答案 所以这个想法是在父组件中保持状态并与子组件共享它作为道具。然后在子组件中对其进行任何我们想要的操作。

Parent.js

export default class CraGenerator extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            number: 0
        }

    getNumberFromChild(data) {
            this.setState({ number: data });
    }

    render() {
        return (
            <div onClick={this.increment.bind(this)}>
                <Child getNumberFromChild={this.getNumberFromChild.bind(this)} number={this.state.number}/>
            </div>
            
        )
}

Child.js

export default class Child extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            number: this.props.number
        }
    }

    increment() {
        this.setState({ number: this.state.number + 1 });
        this.props.getNumberFromChild(this.state.number + 1);
    }

    render() {
        return (
            <div onClick={this.increment.bind(this)}>
                Click me...increment me ::: {this.state.number}
            </div>
        );
    }
}

答案 2 :(得分:0)

将代码的逻辑部分移到父级,而将子级保留为按钮和文本。这样做:

 export const Parent = (props) => {
  const [count, setCount] = React.useState(0);

  const handleCount = () => {
    setCount = count + 1
  }

  return (
    <View>
      <Text>Parent: {count}</Text>
      <Child updateCount={setCount} count={count}/>
    </View>
  );
};

const Child = (props) => {

  return (
    <View>
      <Text>Child: {props.count}</Text>
      <Button title="add" onPress={()=>props.updateCount()} />
    </View>
  );
};

答案 3 :(得分:0)

我做了一个例子here

const updateCount = () => {
  setCount((count) => count + 1); // <=== you did it here correctly
  return props.updateCount(count); // the problem is here
};

发生这种情况是因为它没有收到最新的 count 值,这是在下一次重新渲染时发生的,所以它总是落后一步。要解决此问题,只需执行相同的操作,此处的 return 是多余的。

const updateCount = () => {
  setCount((count) => count + 1);
  props.updateCount((count) => count + 1); // problem fixed
};