一般来说,在单个组件中使用一个或多个 useEffect 钩子更好吗?

IT技术 reactjs performance react-hooks architecture use-effect
2021-04-21 07:34:44

我有一些副作用要应用到我的 React 组件中,并且想知道如何组织它们:

  • 作为单次使用效果
  • 或几个 useEffects

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

3个回答

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

第一:您可能会遇到需要在初始安装期间添加事件侦听器并在卸载时清理它们的情况,以及另一种需要清理特定侦听器并在 prop 更改时重新添加的情况。

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

第二:当任何状态或props从定义的集合发生变化时,您需要触发 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])
@computrius是的React will apply every effect used by the component, in the order they were specified.
2021-05-29 07:34:44
它们是否总是按照定义的顺序触发?即总是先调用 effect1,然后调用 effect2?
2021-05-30 07:34:44
上面第二个第三个例子之间的中间立场怎么样?:当状态/道具的子集发生变化时,你有运行的逻辑,但除了一些需要运行的公共代码之外,每个都有单独的逻辑需要运行?您不会使用[](因为它仍然只是您正在等待更改的状态/道具的一个子集)但您也希望重用代码。您是否使用单独的useEffects并将共享代码放在他们分别调用的函数中?
2021-06-08 07:34:44
如果我有多个“componentDidMount”效果(空数组 []),但它们做的事情却截然不同怎么办?我应该将它们放在单个 useEffect 中还是多个中?
2021-06-08 07:34:44
正如下面的答案所暗示的,React 团队建议按关注点分离钩子,因此您可以将其拆分为多个useEffect调用。
2021-06-11 07:34:44

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

我知道,但是如果您解释了关注点分离的原因,以及这是架构概念还是性能概念,这会改善您的答案。
2021-05-22 07:34:44
虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会无效。-来自评论
2021-06-14 07:34:44

这是完全罚款有有多个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]);
报价是链接中的相关部分简单地包含一个链接是一个省力的答案。
2021-05-23 07:34:44
我不认为包含此代码,尤其是脱离上下文,对问题有帮助或相关。
2021-05-25 07:34:44
@Bricky 无论如何,剥离所有代码并添加引号会改变答案太多以证明它是合理的
2021-05-26 07:34:44
您能否添加更多代码,以明确哪些状态setTags正在更新?setTagsAdded函数还是对象?另外,您如何确保“性能和架构”比一个大的 useEffect 更好?
2021-06-01 07:34:44