简体   繁体   English

将道具从国家传递给孩子

[英]Passing Props from State to Child

I am getting data from a WebAPI call in my componentDidMount on my parent react component. 我正在从我的父反应组件上的componentDidMount中的WebAPI调用中获取数据。 I put the values into state. 我将这些值置于状态中。

When I render my form, I am just making custom labels with data (A component), and passing the label text, and the data to this component. 呈现表单时,我只是用数据(一个组件)制作自定义标签,并将标签文本和数据传递到此组件。 (One for each field I am displaying). (我要显示的每个字段一个)。 I pass the values from state, via props, to the child components. 我将状态值通过prop传递给子组件。

But what I am finding is that my child components are rendering without data being populated... as this seems to happen before the api call happens. 但是我发现我的子组件正在渲染而没有填充数据...因为这似乎是在api调用发生之前发生的。 The api happens, the state gets set, but data never gets to the child components. 发生api,状态被设置,但是数据从不到达子组件。 I thought that the props would pass the updated state data to the components. 我认为道具会将更新后的状态数据传递给组件。 I'm wrong. 我错了。 How should I achieve this? 我应该如何实现呢? I want to load the data in my parent, and then render the child components, passing in the data. 我想将数据加载到我的父级中,然后渲染子级组件,并传入数据。

  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>
        )
    }

My display label component is simply this. 我的显示标签组件就是这样。 I'm new to this, and just trying to make reusable components: 我对此并不陌生,只是尝试制作可重用的组件:

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>
        )
    }
}

I need to wait for the API call to complete before I render the form? 我需要等待API调用完成才能呈现表单?

This is a common problem in React. 这是React中的常见问题。 I usually try to resolve it with a pattern that shows some sort of loading indicator. 我通常尝试使用显示某种加载指示器的模式来解决它。 So I would initialize your state like this in the constructor: 所以我将在构造函数中像这样初始化您的state

    this.state = {
        loading: true
    }

And I would change your render to have a check for that loading bool: 我会更改您的render以检查是否有loading bool:

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>
    )
}

Then you can set loading to false following a successful data pull, and your form will display correctly without any errors. 然后,您可以在成功提取数据后将loading设置为false ,您的表单将正确显示而不会出现任何错误。

(I edited this to use your parent component rather than DisplayLabel , as it makes more sense there. However, the component name is omitted from your question). (我将其编辑为使用您的父组件而不是DisplayLabel ,因为在那里更有意义。但是,您的问题中省略了组件名称)。

I'm not sure you have to wait until the request complete (but you most likely do have to for UI issues), but i guess your problem is something else. 我不确定您是否要等到请求完成(但是您很可能必须针对UI问题),但是我想您的问题是其他问题。

you took the props and included them inside your state (that's unneccery), and then when the component complete it's loading you update the state again, but the request probbaly compleate after the componnent complete it's loading. 您拿走了道具并将它们包含在状态中(这是毫不费力的),然后在组件完成加载时再次更新状态,但是请求在组件完成加载后可能会完成。

if you must to put the props inside your state, you should add componentDidUpdate or componentWillReceiveNewProps lifecycle functions, not the componentDidMount. 如果必须将道具放入状态,则应添加componentDidUpdate或componentWillReceiveNewProps生命周期函数,而不是componentDidMount。

but, if you don't have to (most likley), you might change your render funcion to: 但是,如果不必(最喜欢),则可以将渲染功能更改为:

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>
        )
    }

(just changed the state to props) (只是将状态更改为道具)

Try that, Good Luck! 试试吧,祝你好运!

Just because constructor called once when component mount so you can do one thing, in your render take two var and assign data into that. 正因为构造函数在组件安装时调用了一次,所以您可以做一件事,所以在渲染中使用两个var并将数据分配到其中。 And then use those variable to show data. 然后使用这些变量显示数据。 Because child component will render Everytime state of parent will change but constructor will not. 因为子组件将呈现父对象的Everytime状态,但构造函数不会更改。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM