Компонент не обновляется при смене реквизита, который я передаю ему в React - PullRequest
1 голос
/ 10 октября 2019

У меня есть функциональный компонент, который имеет дочерний компонент. Дочерний компонент отображает некоторый текст, который передается на него от родительского компонента через реквизит. Когда я изменяю текст в родительском компоненте и передаю его, дочерний компонент все еще содержит старый текст.

Ниже приведен минимальный воспроизводимый пример родительского компонента, MainPage.

function MainPage(){
    let text = "This is the original text";
    setTimeout(function(){ text = "This is the new text" }, 3000);
    return(<DisplayText text={text} />);
}

Ниже показан DisplayText.

function DisplayText(props){
    return(<p>{props.text}</p>)
}

Как обновить дочерний компонент, чтобы он отображал «Это новый текст» вместо «Это оригинальный текст» после3 секунды?

Заранее спасибо!

Ответы [ 2 ]

1 голос
/ 10 октября 2019

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

Вы можете выбрать один из двух вариантов: либо следовать примеру обработчиков реакции, опубликованному Luze (в котором отсутствует функция useEffect, которая вызовет setTimeout после загрузки компонента), либо преобразовать родительский компонент в класс. , следующим образом:

import React from 'react';

class MainPage extends React.Component {
  state={
      text: "This is the original text",
  };

  componentDidMount(){
     setTimeout(()=> { this.setState({
        text: "This is the new text"
      }) 
     }, 3000);
  }

  render(){
    return(<DisplayText text={text} />);
  }

}
1 голос
/ 10 октября 2019

Компонент обновляется только один раз, либо state изменяется, либо props изменяется. state - это переменная или набор переменных, которые запоминаются при повторном рендеринге компонента. Все остальные переменные вернутся к своим значениям по умолчанию, как только компонент перезапустится. Вы можете видеть это как память компонента.

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

Если вы хотите, чтобы ваш родительский компонент обновил его состояние (и обновил реквизиты child), вам нужно объявить вашу текстовую переменную следующим образом:

const [text, setText] = React.useState("This is the original text");

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

setText - это функция, которая обновляет переменную text, а также воспроизводит ваш компонент и его дочерние элементы. Вы можете дать этому любое имя.

"Это оригинальный текст" - это ваше начальное состояние, начальное значение вашей переменной text.

Чтобы обновить свое состояние, вы можете сделать что-то вроде этого:

setText("This is the new text");

Так что в вашем случае это будет выглядеть примерно так:

function MainPage(){
    const [text, setText] = React.useState("This is the original text");

    React.useEffect(() => {
        const timeout = setTimeout(function(){
            setText("This is the new text")
        }, 3000);

        return clearTimeout(timeout)
    }, []);

    return(<DisplayText text={text} />);
}

useEffect необходимо, чтобы иметь возможность определить ваш setTimeout, как только компонент монтируется. Его можно использовать для выполнения некоторого кода, как только обновится определенная переменная (определенная в скобках []). Например: если вы написали это так:

React.useEffect(() => {
    // execute some code
}, [text])

Будет выполнено некоторое количество кода, как только ваши переменные text изменятся. Оставьте скобки [] пустыми, чтобы запускать useEffect только тогда, когда компонент монтируется и демонтируется.

В хуке useEffect вы объявляете свой setTimeout, это устанавливает ваш таймер, как только компонент монтируется в этом случае,Метод return в вашем useEffect снова очищает время ожидания, как только компонент отключается. Это предотвратит бесконечную работу вашего таймера после размонтирования компонента.

...