【问题标题】:How to update state of parent from child component in reactJSreactjs如何从子组件更新父组件的状态
【发布时间】:2019-09-22 11:58:55
【问题描述】:
class A extends Component {

  constructor(props) {
    super(props);
    this.state = {
      fruitsDetailsList: [],
      fruitCode: this.props.fruitCode,
    };
  }

  showModal = () => {
    this.setState({ show: true });
  };

  hideModal = () => {
    this.setState({ show: false });
  };

  componentDidMount() {
    const url = 'http://localhost:3000/getFruitslist'; 
    fetch(url, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        fruitCode: this.state.fruitCode,
      }),
    })
    .then(res => {
      if (res.ok) {
        return res.json();
      }
      throw new Error(res.status);
    })
    .then(res => {
      this.setState({
        fruitsDetailsList: res.fruitDetailsList,
      });
    })
    .catch(error => {});
  }
  render() {
    const columns = [
      {
        Header: 'Sr.No',
        id: "row",
        maxWidth: 50,
        Cell: (row) => {
          return <div>{row.index + 1}</div>
        }
      },
      {
        Header: 'Actions',
        id: 'FruitName',
        accessor: d => (
          <div>
            <B/>
          </div>
        )
      }
    ];

    return (
      <div>
        <ReactTable
          className="-striped -highlight"
          columns={columns}
          data={this.state.fruitsDetailsList}
          defaultPageSize={10}
          noDataText={'No Data available.'}
        />
        <p></p>
      </div>
    );
  }

  Class B extends component{
    constructor(props) {
      super(props);
      this.state = { modal: false };
      this.toggle = this.toggle.bind(this);
    }

    toggle() {
      this.setState({
        modal: !this.state.modal
      });
    }

    render() {
      return (
        <div>
          <Button onClick={this.toggle}/>
          <Modal isOpen={this.state.modal}>
            <ModalHeader>Fruits list</ModalHeader>
            <ModalBody>
              <Formik
                initialValues={{fruitName: ''}}
                onSubmit={(fields, action) => {
                  action.setSubmitting(true);
                  const url = 'http://localhost:3000/getFruit';
                  fetch(url, {
                    method: 'POST',
                    headers: {
                      'Content-Type': 'application/json',
                    },
                    body: JSON.stringify({
                      fruitName: fields.fruitName,
                    }),
                  })
                  .then(res => {
                    action.setSubmitting(false);
                    console.log("Success!!!);
                  })
                  .catch(error => {});
                }}
                render={({ errors, touched, isSubmitting }) => (
                  !isSubmitting ? (
                    <Form>
                      <div className="form-group">
                        <label htmlFor="fruitName">FruitName</label>
                        <Field name="fruitName" type="text"/>
                      </div>
                      <div className="form-group">
                        <Button type="submit" className="bg-gradient-theme-left border-0 " size="m">Submit</Button>
                      </div>
                    </Form>
                  )
                )}
              />
              </ModalBody>
            </Modal>
          </div>
        );
      }
    }

- 反应 JS

如您所见,有 2 个类 1)A组份 2)B组份
在组件 A 中,我将 B 组件称为 react-table 中的 Button

实际上,我们必须通过调用我们在组件 A 的 componentDidMount 中调用的 post API 请求 '/getFruitslist' 来渲染带有数据库中所有数据的反应表,以便反应表中的数据正确填充到表中

现在,当我们单击组件 B 的按钮时,会插入一条记录 数据库,但在组件 A 的 ComponentDidMount 中调用 API,即 组件 B 的父级,单击 B 组件的按钮时,数据不会填充到反应表中。如何做到这一点?

【问题讨论】:

  • 在组件A 中创建一个函数,它将在状态中添加fruitName。将该函数传递给组件B。当表单提交调用该函数并传递fruitName。随着父组件中的状态发生变化,它也会反映在表格中。

标签: reactjs


【解决方案1】:

React 的哲学是将状态管理到顶层组件中。子组件不应保留对其父组件的引用以更新父状态。 为了实现这个行为,父组件应该通过其属性向子组件传递一个回调,然后子组件可以通过调用匹配的属性来调用这个回调

在您的示例中,您可以将属性 onAddFruit 传递给 B 组件。当POST调用成功时,应该调用这个函数

.then(fruit => {
  action.setSubmitting(false);
  console.log("Success!!!);
  this.props.onAddFruit(fruit);
})

在父组件A 中,您定义了一个函数,它将向状态变量fruitsDetailsList 添加一个水果。然后你通过属性onAddFruit将这个函数传递给组件B

handleAddFruit = fruit => {
   this.setState(prevState => ({
     fruitsDetailsList: [...prevState.fruitsDetailsList, fruit]
   });
};

B 元素的声明如下:

<B onAddFruit={this.handleAddFruit}/> 

【讨论】:

    【解决方案2】:

    有多种方法可以实现您的目标。最简单的一种是通过props 传递必要的对象、值。在复杂的情况下,我建议使用redux 进行应用程序状态管理,当您需要在多个组件中访问状态对象时,保持状态一致会更容易。

    传递道具:

    一旦您拥有 2 个组件,就可以将数据从 A 向下传递到 B。分享以下 1 个小示例,您可以如何实现这一目标:

    class A extends Component {
       constructor(props) {
          super(props);
          this.state = {
             fruitsDetailsList: [],
             fruitCode: this.props.fruitCode,
          };
       }
    
       render {
           return (
              <B dataFromA={this.state.fruitsDetailsList} />
           )
       }
    }
    

    Redux 选项:

    那么什么是 Redux?

    JavaScript 应用程序的可预测状态容器。

    基本上,如果您的应用程序需要使用来自reduxmapStateToProps 函数访问状态对象,您可以将其与每个组件相匹配的1 个公共位置。链接Connect: Extracting Data with mapStateToProps 更详细地解释了如何做到这一点。一旦您需要修改任何元素,您可以使用mapDispatchToProps 来执行此操作。请找到Connect: Dispatching Actions with mapDispatchToProps 链接以进行进一步设置。

    进一步了解设置,从这里开始:Redux

    总结:

    在您的场景中,由于 API 调用,状态对象可能会频繁更新,我建议使用第二个选项。乍一看可能很复杂,但值得努力,因为您无需担心状态一致性,并且通过props,一旦您对任何对象进行了修改,数据就会自动更新。

    我希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 2018-04-20
      • 2021-06-08
      • 2017-11-05
      • 2017-09-28
      • 2019-06-03
      • 2023-02-19
      • 1970-01-01
      • 2015-04-15
      • 2018-10-05
      相关资源
      最近更新 更多