将 props 从 state 传递给 child

IT技术 javascript reactjs
2021-05-18 01:45:53

我从父 React 组件上的 componentDidMount 中的 WebAPI 调用获取数据。我将值放入状态。

当我呈现我的表单时,我只是用数据(一个组件)制作自定义标签,并将标签文本和数据传递给这个组件。(我显示的每个字段一个)。我通过 props 将 state 中的值传递给子组件。

但我发现我的子组件在没有填充数据的情况下渲染......因为这似乎发生在 api 调用发生之前。api 发生,状态被设置,但数据永远不会到达子组件。我认为props会将更新的状态数据传递给组件。我错了。我应该如何实现这一目标?我想在我的父组件中加载数据,然后渲染子组件,传入数据。

  componentDidMount() {
        this.loadData();
    }

    loadData() {
        var request = {
            method: 'GET',
            URL: "http://example.com/api/user/profile",
        }

        fetchData(request).then(response => {
            if(response.errorcode != "OK")
            {
                console.log("Bad response from API. Need to redirect!")
            }
            else
            {
                this.setState(
                    {
                        firstname: response.payload.firstname, 
                        surname: response.payload.surname,
                        email: response.payload.email,
                        countryId: response.payload.countryId,
                        countries: response.payload.countries
                    }
                );
            }
        });
    }

    render() {
        return (
            <div>
                <h2>Your Profile</h2>
                <div className="row">
                    <div className="col-xs-6">
                        <DisplayLabel labelText={"Firstname"} data={this.state.firstname} />
                        <DisplayLabel labelText={"Surname"} data={this.state.surname} />
                        <DisplayLabel labelText={"Email Address"} data={this.state.email} />
                        <DisplayLabel labelText={"Country"} data={this.state.countryId} />
                        <div className="form-group row right">
                            <button className="btn btn-primary" onClick={this.openModal}>Edit</button>
                        </div>
                    </div>
                </div>
                <Modal isOpen={this.state.modalIsOpen} onAfterOpen={this.afterOpenModal} style={modalStyle}>
                    <ProfileEditBox closeMeCallback = {this.closeModal} />
                </Modal>
            </div>
        )
    }

我的显示标签组件就是这样。我是新手,只是想制作可重用的组件:

import React, {Component} from 'react';

export default class DisplayLabel extends Component {
    constructor(props)
    {
        super(props);
        this.state = {
            labelText: this.props.labelText,
            data: this.props.data
        }
        console.log(this.state);

    }

    componentDidMount() {
        this.setState({
            labelText: this.props.labelText,
            data: this.props.data
        });
        console.log("ComponentDidMount", this.state);

    }

    render() {
        return (
            <div>
                <div className="row">
                    <div className="col-xs-12">
                        <label className="control-label">{this.state.labelText}</label>
                    </div>
                </div>
                <div className="row">
                    <div className="col-xs-12">
                        &nbsp;&nbsp;<strong><span>{this.state.data}</span></strong>
                    </div>
                </div>
            </div>
        )
    }
}

在呈现表单之前,我需要等待 API 调用完成吗?

3个回答

这是 React 中的常见问题。我通常尝试使用显示某种加载指示器的模式来解决它。所以我会state在构造函数中像这样初始化你

    this.state = {
        loading: true
    }

我会改变你render检查那个loading布尔值:

render() {
    if (this.state.loading) {
        return (<h1>Loading, please wait...</h1>);
    }
    return (
        <div>
            <h2>Your Profile</h2>
            <div className="row">
                <div className="col-xs-6">
                    <DisplayLabel labelText={"Firstname"} data={this.state.firstname} />
                    <DisplayLabel labelText={"Surname"} data={this.state.surname} />
                    <DisplayLabel labelText={"Email Address"} data={this.state.email} />
                    <DisplayLabel labelText={"Country"} data={this.state.countryId} />
                    <div className="form-group row right">
                        <button className="btn btn-primary" onClick={this.openModal}>Edit</button>
                    </div>
                </div>
            </div>
            <Modal isOpen={this.state.modalIsOpen} onAfterOpen={this.afterOpenModal} style={modalStyle}>
                <ProfileEditBox closeMeCallback = {this.closeModal} />
            </Modal>
        </div>
    )
}

然后您可以设置loadingfalse关注成功的数据拉取,您的表单将正确显示而不会出现任何错误。

(我对此进行了编辑以使用您的父组件而不是DisplayLabel,因为它在那里更有意义。但是,您的问题中省略了组件名称)。

我不确定您是否必须等到请求完成(但对于 UI 问题,您很可能必须这样做),但我想您的问题是其他问题。

您获取了props并将它们包含在您的状态中(这是不必要的),然后当组件完成加载时,您再次更新状态,但是在组件完成加载后,请求可能会完成。

如果你必须把 props 放在你的 state 中,你应该添加 componentDidUpdate 或 componentWillReceiveNewProps 生命周期函数,而不是 componentDidMount。

但是,如果您不必(最喜欢),您可以将渲染功能更改为:

render() {
        return (
            <div>
                <div className="row">
                    <div className="col-xs-12">
                        <label className="control-label">{this.props.labelText}</label>
                    </div>
                </div>
                <div className="row">
                    <div className="col-xs-12">
                        &nbsp;&nbsp;<strong><span>{this.props.data}</span></strong>
                    </div>
                </div>
            </div>
        )
    }

(只是把状态改成了props)

试试看,祝你好运!

仅仅因为构造函数在组件挂载时调用一次所以你可以做一件事,在你的渲染中使用两个 var 并将数据分配给它。然后使用这些变量来显示数据。因为子组件会渲染每次父组件的状态都会改变但构造函数不会。