Как получить доступ к текущему состоянию компонента из useEffect, не делая его зависимым? - PullRequest
0 голосов
/ 27 февраля 2020

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

const NoteViewer = (props) => {
    const [note, setNote] = useState({ title: '', hasChanged: false });

    useEffect(() => {
        const note = loadNote(props.noteId);
        setNote(note);

        return () => {
            if (note.hasChanged) saveNote(note); // bug!!
        }
    }, [props.noteId]);

    const onNoteChange = (event) => {
        setNote({ ...note, title: event.target.value, hasChanged: true });
    }

    return (
        <input value={note.title} onChange={onNoteChange}/>
    );
}

Проблема заключается в том, что в useEffect, который я использую note, который не является частью зависимостей, так что это означает, что я всегда получаю устаревшие данные.

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

Поэтому мне интересно, как я могу получить доступ к текущей заметке, не делая ее зависимой? Я пытался заменить заметку на ссылку, но это означает, что компонент больше не обновляется при изменении заметки, и я бы предпочел не использовать ссылки.

Любая идея, что будет лучшим способом достичь этого? Может быть, какая-то особая модель React Hooks?

1 Ответ

2 голосов
/ 27 февраля 2020

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

Использование функции очистки эффекта не подходит для такого рода вещей. Это действительно должно быть зарезервировано для очистки этого эффекта и ничего больше.

Вместо этого, какие бы логики c у вас не были в приложении, которое изменяет состояние для закрытия NoteViewer, также следует сохранять заметку. Таким образом, в некотором родительском компоненте (возможно, NoteList или что-то) вы сохраните и закроете, как:

function NoteList() {
  const [viewingNoteId, setViewingNoteId] = useState(null)

  // other stuff...

  function closeNote() {
    if (note.hasChanged) saveNote(note)
    setViewingNoteId(null)
  }

  return <>{/* ... */}</>
}
...