Реквизиты передаются от родителя к ребенку, и установка этих реквизитов в состояние не работает сразу - PullRequest
0 голосов
/ 11 апреля 2019

Я создаю приложение, в котором я получаю "жалобы" из моего приложения Nodejs.Затем я передаю эти жалобы дочернему компоненту в качестве реквизита.В дочернем компоненте я установил эти реквизиты в состояние ComponentDidMount().Но сначала вызывается функция render(), поэтому на экране ничего не отображается.Состояние не устанавливается сразу.пожалуйста помоги.Я борюсь с 2 дня.

это родительский компонент

class Complainer extends Component {
  state = {
    complaints: []
  };

  async componentDidMount() {
    try {
      const user = auth.getCurrentUser();
      console.log(user);
      this.setState({ user });
      if (!user || user.role !== 'complainer') this.props.history.replace('/');
    } catch (ex) {
      window.location = '/login';
    }

    const { data: complaints } = await getComplaints();
    this.setState({ complaints });
  }

  render() {
    const { complaints } = this.state;
    return (
      <React.Fragment>
        <Navbar user={this.state.user} />
        <div className="container">
          <Switch>
            <Route
              path="/complainer/view-all"
              render={props => (
                <AllComplaints complaints={complaints} {...props} />
              )}
            />
            <Route path="/complainer/new-complaint" component={ComplaintForm} />
            <Route path="/complainer/not-found" component={notfound} />
            <Showcase user={this.state.user} />
          </Switch>
          <hr />
        </div>
      </React.Fragment>
    );
  }
}

export default Complainer;

Это дочерний

class AllComplaints extends Component {
  state = {
    data: {
      columns: [
        {
          label: 'location',
          field: 'location',
          sort: 'asc',
          width: 280
        },
        {
          label: 'Title',
          field: 'title',
          sort: 'asc',
          width: 150
        }
      ],

      rows: []
    }
  };

  componentDidMount() {
    const { complaints } = this.props;
    this.setState({ rows: complaints });
  }

  render() {
    const { data } = this.state;
    return (
      <React.Fragment>
        {data.rows && <MDBDataTable striped bordered small data={data} />}
        {!data.rows && <h1>There is no complaints to show</h1>}
      </React.Fragment>
    );
  }
}

export default AllComplaints;

Проблема в том, что в состоянии строки пустые.то есть [].в componentDidMount() я устанавливаю ближайшие реквизиты в состояние этого компонента «AllComplaints».

Я хочу установить значение "props" в "this.state.data.rows".Но этого не происходит.Для установки требуется время, но сначала вызывается render(), поэтому на экране ничего не отображается.

Пожалуйста, помогите.

Ответы [ 3 ]

2 голосов
/ 11 апреля 2019

Похоже, вы устанавливаете не this.state.data.rows, а this.state.rows и используете this.state.data.rows внутри рендера

0 голосов
/ 11 апреля 2019

Две вещи:

Как уже упоминалось @karahan, вы неправильно устанавливаете свое состояние.

this.setState({ rows: complaints });

должно быть что-то вроде:

this.setState(prevState => { data: { ...prevState.data, rows: complaints } });

Однако этого, вероятно, будет недостаточно. Вы извлекаете свои данные у componentDidMount родителя и устанавливаете свое состояние в componentDidMount ребенка. Однако componentDidMount дочернего элемента всегда запускается первым, если они монтируются одновременно, и запускается только один раз. Это означает, что с вашей настройкой, props.complaints вашего ребенка может быть пустым в componentDidMount.

Я бы решил эту проблему, не используя state в компоненте вашего ребенка. Редко есть веская причина хранить одно и то же состояние в нескольких компонентах (в этом случае вы храните одно и то же в родительском и дочернем элементах). Просто используйте ваш реквизит, который всегда будет актуален в вашей функции рендеринга. Ваш рендеринг MDBDataTable должен выглядеть примерно так:

<MDBDataTable striped bordered small data={{ ...this.state.data, rows: this.props.complaints }} />

Если по какой-то причине вам абсолютно необходимо хранить complaints в состоянии ребенка, вам следует либо вместо этого получить данные у ребенка, либо просмотреть getDerivedStateFromProps и componentDidUpdate. Однако вряд ли вам понадобится такая настройка.

0 голосов
/ 11 апреля 2019

Если вы хотите использовать жалобы во время рендеринга, вам нужно инициализировать их в вашем состоянии.

вам нужно написать конструктор для вашего класса, который будет принимать реквизиты от родительского компонента и использовать его для определения начального состояния строк.

class AllComplaints extends Component {

    constructor(props) {
        super(props);
        this.state  = {
            data: {
              columns: [
                {
                  label: 'location',
                  field: 'location',
                  sort: 'asc',
                  width: 280
                },
                {
                  label: 'Title',
                  field: 'title',
                  sort: 'asc',
                  width: 150
                }
              ],

              rows: props.complaints
            }
          };
        }
          componentDidMount() {
//commeting below lines as you do not need them as of now.
            //const { complaints } = this.props;
            //this.setState({ rows: complaints });
          }

          render() {
            const { data } = this.state;
            return (
              <React.Fragment>
                {data.rows && <MDBDataTable striped bordered small data={data} />}
                {!data.rows && <h1>There is no complaints to show</h1>}
              </React.Fragment>
            );
          }
        }

        export default AllComplaints;
...