Компонент сохранит состояние после его размонтирования

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

Я создаю форму обратной связи с 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, но в чем же тогда моя ошибка?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
2
0
460
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вышеупомянутое поведение происходит потому, что эффект также запускается при начальном рендеринге, и в этом случае 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]);
}

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

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

Другие вопросы по теме