Реквизиты, передаваемые от родителя к дочернему, и установка этих реквизитов в состояние не работает немедленно.

Я создаю приложение, в котором получаю «жалобы» от моего приложения 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".

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

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


person Makki Anjum    schedule 11.04.2019    source источник
comment
Есть ли особая причина, по которой вы используете здесь состояние? Почему бы просто не использовать <MDBDataTable data={this.props.complaints} />? Кроме того, где ваши данные извлекаются? Это в componentDidMount родителя? Если это так, вы должны включить в свой вопрос родительские функции componentDidMount и render.   -  person Dylan Walker    schedule 11.04.2019
comment
Я включил родителя сейчас. Пожалуйста, посмотрите.   -  person Makki Anjum    schedule 11.04.2019


Ответы (3)


Две вещи:

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

this.setState({ rows: complaints });

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

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

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

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

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

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

person Dylan Walker    schedule 11.04.2019
comment
‹MDBDataTable полосатые малые данные={{ ...this.state.data, rows: this.props.complaints }} /› . это сработало для меня. большое спасибо дружище! спасибо - person Makki Anjum; 11.04.2019

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

person karahan    schedule 11.04.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;
person Manoj    schedule 11.04.2019