React app componentDidMount не получает реквизиты от родителя

Я пытаюсь передать реквизиты родительского компонента дочернему компоненту, и хотя он вызывается дважды (не знаю почему, componentDidMount должен вызываться только один раз), реквизиты кажутся пустыми.

Родительский компонент:

class Members extends Component{
    constructor(props){
        super(props);
        this.state = {
            interests: []
        }
    }

    componentDidMount(){
        fetch(interestUrl, {
            method: 'GET',
            headers: {
              "Content-Type": "application/json",
              "Authorization": this.props.authToken
            }
        })
        .then((response) => response.json())
        .then((json) => {this.setState({interests: json})})
        .catch(error => {console.log("Error: " + error)})
    };

    render(){
        return(
            <div className="Members-body">
                <div className="Menu-sidebar">
                    <Menu interestList = {this.state.interests}/>
                </div>
                <div className="Main-container">
                    <Main/>
                </div>
            </div>
        )
    }

}
export default Members;

Дочерний компонент:

class Menu extends Component {
    constructor(props){
        super(props);
    }

    componentDidMount(){
        console.log("interestList: "  + this.props.interestList);
    }

    render() {
        return(
            <div className="Menu-container">
                este es el menu de la aplicacion
            </div>
        )
    }
}

export default Menu;

Журнал консоли из componentDidMount внутри компонента Menu печатает:

interestList: 
interestList: 

Есть идеи указать мне в правильном направлении? Высоко оценен!


person Dieguinho    schedule 30.04.2018    source источник
comment
Вы уверены, что компонент меню не загружен в двух местах вашего пользовательского интерфейса. Вы также можете убедиться, что компонент Main не указывает на Menu   -  person Shubham Khatri    schedule 30.04.2018
comment
также console.log верна. вы можете проверить это в консоли "foo: " + []   -  person azium    schedule 30.04.2018
comment
возможный дубликат stackoverflow.com/questions/43779411/   -  person Shubham Khatri    schedule 30.04.2018
comment
@ShubhamKhatri: да, я уверен, компонент, который действительно отрисовывает дважды, - это компонент Members, компоненты Main и Menu - простые Html, я сделал еще одно сообщение с кодом для проблемы двойного рендеринга, взгляните на него здесь: ссылка. Только что увидел вашу ссылку на дубликат, в моем случае я использую componentDidMount, поэтому он должен вызываться после рендеринга компонента и должен иметь реквизиты, переданные родителем   -  person Dieguinho    schedule 30.04.2018
comment
@azium, это правильно, дело в том, что первый вызов пуст, но второй вызов возвращает массив с информацией, а не пустой массив, поэтому он должен отображаться в консоли   -  person Dieguinho    schedule 30.04.2018
comment
нет, это не должно отображаться в консоли именно потому, что componentDidMount запускается только один раз, когда компонент монтируется. когда компонент Members вызывает setState и передает новые реквизиты в Menu, он уже смонтирован, так что эта функция и журнал консоли больше не будут вызываться с заполненным массивом. вы можете легко это проверить, переместив журнал консоли в функцию render   -  person azium    schedule 30.04.2018
comment
@azium, хорошо, я не понимаю, помещая console.log внутри функции рендеринга, он отображает его 3 раза, что означает, что он в третий раз вызывается из другого жизненного цикла, помимо жизненного цикла de create. Вы правы, третий раз печатает props, но разве компонент не должен получать props до своего создания? Я имею в виду, я читал, что конструктор вызывается до того, как компонент выполняет рендеринг, и таким образом получает реквизиты от родителя ...   -  person Dieguinho    schedule 30.04.2018
comment
Компонент получает свойства перед созданием, но свойство представляет собой пустой массив. Вы явно указываете это в своем конструкторе Members. Затем после Members монтирования вы вызываете setState, который запускает другой рендеринг с заполненным массивом. Прочтите документы, чтобы получить полное объяснение.   -  person azium    schedule 30.04.2018


Ответы (2)


Для ответа посмотрите комментарии @azium:

нет, это не должно отображаться в консоли именно потому, что componentDidMount запускается только один раз, когда компонент монтируется. когда компонент Members вызывает setState и передает новые реквизиты в Menu, он уже смонтирован, так что эта функция и журнал консоли больше не будут вызываться с заполненным массивом. Вы можете легко это проверить, переместив журнал консоли в функцию render.
Компонент получает реквизиты перед созданием, но этот реквизит представляет собой пустой массив. Вы явно указываете это в своем конструкторе Members. Затем после Members монтирования вы вызываете setState, который запускает другой рендеринг с заполненным массивом. Прочтите документы, чтобы получить полное объяснение.

person Dieguinho    schedule 01.05.2018
comment
как справиться с такими сценариями? (без редукции) - person Hem M; 18.12.2020

Если вы планируете манипулировать этой опорой в своем компоненте, создайте состояние в своем компоненте и назначьте ему эту опору. Вы по-прежнему не сможете сделать это в componentDidMount, но вы можете использовать там componentDidUpdate и setState. Предупреждение, убедитесь, что вы всегда запускаете сравнение с prevProps, иначе вы получите ошибку типа бесконечного цикла.

class Menu extends Component {
    constructor(props){
        super(props);
        this.state = {
          interestList: []
        };
    }

      componentDidUpdate(prevProps) {
        // compare props
        if (this.props.interestList !== prevProps.interestList) {
          this.setState({
            interestList: this.props.interestList
          })
        }
      }
    componentDidMount(){
        // won't work
        console.log("interestList: "  + this.props.interestList);
    }

    render() {
        return(
            <div className="Menu-container">
                este es el menu de la aplicacion
            </div>
        )
    }
}

export default Menu;
person sigmapi13    schedule 14.01.2021