代码之家  ›  专栏  ›  技术社区  ›  Phil Lucks

如何防止useffect中的函数被多次触发?

  •  0
  • Phil Lucks  · 技术社区  · 5 年前

    有一个ESLint规则 exhaustive-deps useEffect ). 我的问题是,由于像现在正在跟踪的函数这样的事情,useEffect的内容被更频繁地触发会产生什么样的影响。
    当api调用位于效果内部时,这可能会产生负面影响,因为您只希望api被调用一次。

    如何防止内容被触发的次数超过其需要的次数? 对我来说,为了防止对API服务的额外调用,我要么需要忽略lint规则(不!)或者对我的代码进行更多的检查,以及对状态进行本地检查:

    防止多次触发会话和api调用的示例:

    useEffect(() => {
        if (!saveValues) {  // is this an anti-pattern?
          return;
        }
        if (!sessionId && !wasSaving && savingForm) {
          initSession().then(() => { // 1st call to session service to get Id
            setSendRequest(true); // set local state that it's safe to send API request because I have my session ready
          });
        } else if (sendRequest && sessionId) {
          setSendRequest(false); // immediately set local state back to false so the previous block doesnt fire.
          try {
            const fields = userFields
              .filter(field => !isEmpty(saveValues[field.name]))
              .map(field => {
                  name: field.name,
                  value,
                };
              );
            insertUser({ sessionId, fields, config, newRoles }) // here's my API call now
              .then(() => saveSession(sessionId)) // 2nd call to session service req'd
          } catch (err) {
            const message = err.message.split('desc = ')[1];
            setSaveRequestError(message);
            setSavingForm(false);
            setSaveModalOpen(false);
            quitSession(sessionId);
          }
        }
        return () => {
          if (sessionId) {
            quitSession(sessionId);
          }
        };
      }, [
        initSession,
        insertUser,
        quitSession,
        roles.rolesList,
        saveSession,
        saveValues,
        savingForm,
        sendRequest,
        sessionId,
        userFields,
        wasSaving,
      ]);
    

    0 回复  |  直到 5 年前
        1
  •  0
  •   Bonje Fir    5 年前

    由于react文件 here here 最好把你的每一个条件都单独考虑 useEffect 而不是一个复杂的。每个 使用效果 有自己的依赖数组并执行特定的任务。

        2
  •  0
  •   Taxel    5 年前

    如果您只是想避免再次执行它(并且您不想传递一个空的dep数组),useRef是您的朋友,因为它不会重新呈现组件(不是一个状态):

    let hasBeenExecuted = useRef(false);
    //In effect
    if(!hasBeenExecuted.current) {
        // Do stuff
        hasBeenExecuted.current = true
    }
    
        3
  •  -2
  •   Sawan Patodia    5 年前

    如果希望useffect中的代码仅在组件最初加载时调用,请将空数组作为依赖项传递。