Компонент сохранит состояние после размонтирования - PullRequest
2 голосов
/ 01 апреля 2019

Компонент будет сохранять состояние даже после размонтирования

Я создаю форму обратной связи с Formik и хочу перейти от компонентов класса к перехватчикам, но столкнулся с упомянутыми трудностями.

function Feedback(props) {
  const [fileInfo, setFileInfo] = useState("");
  const [feedbackStatus, setFeedbackStatus] = useState("");
  let timer = null;

  useEffect(() => {
    const status = props.feedbackResponse.status;

    if (status) {

      if (status >= 200 && status < 300) {
        setFeedbackStatus("success");
        timer = setTimeout(() => {
          props.history.goBack();
        }, 2500);
      } else if (status === "pending") {
        setFeedbackStatus("pending");
      } else {
        setFeedbackStatus("error");
      }

    }
    return () => {
      clearInterval(timer);
    }
  }, [props.feedbackResponse.status]);

  // ...code ommited for brevity
}

Этот эффект успешно выполняется после отправки моей формы в ожидании ответа сервера. Feedback компонент - это react-router модальный компонент, если это имеет значение. Однако, если я снова открою этот модал, вместо новой формы я увижу сообщение об успехе. В моем return я условно отображаю сообщение об успехе, если feedbackStatus === "success" или форма, которая в зависимости от ответа сервера может отображать сообщение об ошибке в противном случае. Мой компонент класса отлично работает с этим кодом:

componentDidUpdate(prevProps) {
     const status = this.props.feedbackResponse.status;
     if (prevProps.feedbackResponse.status !== status) {
       if (status >= 200 && status < 300) {
         this.setState({feedbackStatus: "success"});
         this.timer = setTimeout(() => {
           this.props.history.goBack();
         }, 2500);
       } else if (status === "pending") {
         this.setState({feedbackStatus: "pending"});
       } else {
         this.setState({feedbackStatus: "error"});
       };
     }
   }

   componentWillUnmount() {
     clearInterval(this.timer);
   }

Ожидаемый результат: повторное открытие этого модального компонента после успешной отправки формы должно отобразить новую форму, но при этом отобразится предыдущий статус отправки. Это заставляет меня думать, что я вообще не размонтирую Feedback компонент, но где тогда моя ошибка?

Ответы [ 2 ]

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

Вышеупомянутое поведение происходит потому, что эффект запускается и при начальном рендеринге, и в этом случае props.feedbackStatus может быть сохранено из предыдущих экземпляров.

Поскольку вы хотите выполнить эффект только при обновлении компонента, вам необходимо остановить выполнение useEffect при начальном рендеринге , что происходит, даже когда вы передаете значения в массив зависимостей. Вы можете сделать это, используя useRef

function Feedback(props) {
  const [fileInfo, setFileInfo] = useState("");
  const [feedbackStatus, setFeedbackStatus] = useState("");
  const isInitialRender = useRef(true);
  let timer = null;


  useEffect(() => {
    if(isInitialRender.current === true) {
        isInitialRender.current = false;
    } else {
        const status = props.feedbackResponse.status;

        if (status) {

          if (status >= 200 && status < 300) {
            setFeedbackStatus("success");
            timer = setTimeout(() => {
              props.history.goBack();
            }, 2500);
          } else if (status === "pending") {
            setFeedbackStatus("pending");
          } else {
            setFeedbackStatus("error");
          }

        }
   }
        return () => {
          clearInterval(timer);
        }
    }, [props.feedbackResponse.status]);
}
1 голос
/ 01 апреля 2019

Вы можете использовать <Feedback key={someKey} />.

Это обеспечит создание нового экземпляра компонента Feedback при повторном его открытии, поэтому ваши старые сообщения об успехе / неудаче будут стерты из состояния.

...