Должен ли я использовать один или несколько useEffect в компоненте?

У меня есть некоторые побочные эффекты, и я думаю, как их организовать:

  • как одноразовый эффект
  • или несколько useEffects

что лучше с точки зрения производительности и архитектуры?

3 ответа

Решение

Шаблон, которому вы должны следовать, зависит от вашего useCase.

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

useEffect(() => {
   // adding event listeners on mount here
   return () => {
       // cleaning up the listeners here
   }
}, []);

useEffect(() => {
   // adding listeners everytime props.x changes
   return () => {
       // removing the listener when props.x changes
   }
}, [props.x])

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

useEffect(() => {
    // side effect here on change of any of props.x or stateY
}, [props.x, stateY])

Третий: третий случай, когда вам нужно предпринять разные действия при изменении разных значений. В таком случае разделите соответствующие сравнения на разные useEffects

useEffect(() => {
   // some side-effect on change of props.x
}, [props.x])

useEffect(() => {
   // another side-effect on change of stateX or stateY 
}, [stateX, stateY])

Вы должны использовать несколько эффектов, чтобы разделить проблемы, как это предлагается по адресу actjs.org https://reactjs.org/docs/hooks-effect.html

Совершенно нормально иметь несколько useEffect.

Вот как выглядит одна из моих настроек:

      /*
 * Backend tags list have changed add the changes if needed
 */
useEffect(() => {
    setTagsList(setTagsAdded);
}, [setTagsAdded]);

/*
 * Backend files have changed add the changes if needed
 */
useEffect(() => {
    for (let i = 0; i < changedFilesMeta.length; i += 1) {
        // Is the list item value changed
        if (changedFilesMeta[i].id === currentEditableFile.id) {
            unstable_batchedUpdates(() => {
                setTags(changedFilesMeta[i].tags ? changedFilesMeta[i].tags : []);
            });
        }
    }
}, [changedFilesMeta]);

/*
 * Reset when user select new files using the filepicker
 */
useEffect(() => {
    if (setNewFiles.length > 0) {
        unstable_batchedUpdates(() => {
            setCurrentFile(null);
            setDescription('');
            setTitle('');
            setTags([]);
        });
    }
}, [setNewFiles]);

/*
 * User selecet to edit a file, change to that file
 */
useEffect(() => {
    // When user select a file to edit it
    if (currentEditableFile && currentEditableFile !== theCurrentFile) {
        setCurrentFile(currentEditableFile);
        unstable_batchedUpdates(() => {
            setDescription(currentEditableFile.description);
            setTitle(currentEditableFile.title);
            setTags(currentEditableFile.tags);
        });
    }
}, [currentEditableFile]);
Другие вопросы по тегам