Реакция хука useEffect с долго выполняющейся задачей и состоянием слияния - PullRequest
3 голосов
/ 11 мая 2019

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

Я использую эффект с пустым массивом зависимостей для настройки подписки RXJS, которая обрабатывает удаленные файлы и время загрузки:

const [attachments, setAttachments] = useState([])

useEffect(() => {
    ...
    fileUploadSubject.subscribe(newAttachments => {
       setAttachments([...attachments,newAttachments])
    })
    ...
    return () => {
      subscriptions.forEach(s => {
        s.unsubscribe()
      })
    }
},[])

Проблема в том, что эффект зависит от attachments, а также от функции setAttachments.

Если я добавлю attachments в массив зависимостей, я откажусь от подписки на существующие загрузки. Также состояние attachment не обновляется внутри эффекта из-за его закрытия.

Как мне решить такой сценарий? Я думал о нескольких путях, но, похоже, не могу найти простой путь вперед.

Ответы [ 2 ]

2 голосов
/ 11 мая 2019

Функции setState useState поддерживают функциональные обновления форма:

const [attachments, setAttachments] = useState([])

useEffect(() => {
    ...
    const subscription = fileUploadSubject.subscribe(newAttachments => {
       setAttachments((oldAttachments) => [...oldAttachments, newAttachments])
    })
    ...
    return () => subscription.unsubscribe()
}, [setAttachments, fileUploadSubject])

Функции, которые никогда не меняются (т. Е. Оба здесь), могут быть опущены в списке зависимостей, но япредпочитаю перечислять их, чтобы не забыть какую-то зависимость.Существуют правила отбора для этого крутого.

2 голосов
/ 11 мая 2019

Если я добавлю вложения в массив зависимостей, я откажусь от подписки на существующие загрузки

Не уверен, почему отписался, не знаком с fileUploadSubject.subscribe

Также состояние вложения не обновляется внутри эффекта из-за его закрытия

Вы можете useReducer вместо useState, таким образом вам не нужно зависеть от состояния вашего эффекта.
Может быть, что-то вроде этого:

function reducer(state, action) {
  switch (action.type) {
    case "ADD_ATTACH":
      return [...state, action.payload];
    default:
      throw new Error();
  }
}

function App() {
  const [attachments, dispatch] = useReducer(reducer, []);

  useEffect(() => {
    // ...
    fileUploadSubject.subscribe(newAttachments => {
      dispatch({ type: "ADD_ATTACH", payload: newAttachments });
    });
    // ...
    return () => {
      subscriptions.forEach(s => {
        s.unsubscribe();
      });
    };
  }, [/*fileUploadSubject?,  subscriptions? */]);

  return <div>{ /* some UI */ }</div>;
}

Я все еще думаю, что странно, что ваш эффект ни от чего не зависит, убедитесь, что subscriptions и fileUploadSubject действительно не должны быть внутри массива зависимостей.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...