我有一些副作用应用在我的反应组件,想知道如何组织他们:

作为一个单独的useEffect 或几个useEffects

在性能和架构方面,哪个更好?


当前回答

您需要遵循的模式取决于您的用例。

首先:您可能会遇到这样的情况:在初始挂载期间需要添加事件侦听器,并在卸载时清理它们;在另一种情况下,需要在道具更改时清理并重新添加特定的侦听器。

在这种情况下,使用两个不同的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])

其他回答

您需要遵循的模式取决于您的用例。

首先:您可能会遇到这样的情况:在初始挂载期间需要添加事件侦听器,并在卸载时清理它们;在另一种情况下,需要在道具更改时清理并重新添加特定的侦听器。

在这种情况下,使用两个不同的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])

您应该按照reactjs.org的建议使用多个效果来分离关注点。

有多重使用效果是很好的。

以下是我的其中一个设置:

/*
 * 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]);