【问题标题】:Prevent Redux from rerendering entire tree and clearing local state防止 Redux 重新渲染整个树并清除本地状态
【发布时间】:2020-10-28 12:20:31
【问题描述】:

对于我的应用程序的注册表单,我使用本地组件状态维护表单值,但 currentUser 状态、错误状态和 API 调用都在 Redux 中。

我希望在提交表单时,按钮有一个加载微调器,并且表单值保持不变,直到服务器返回响应。如果服务器以授权用户响应,则重定向到应用程序。如果出现错误,则应清除表单的值。

问题似乎是 Redux 在调度任何状态更新函数时清除了我的表单值(无论是删除错误还是进行 API 调用以授权用户)。有什么办法可以避免这种情况发生吗?

来自我的 AuthForm.js

const submitData = () => {
    setLoading(true);
    if (formType === 'reset') {
      updatePassword(resetToken, values.password, history)
        .then(result => setLoading(false));
    } else if (formType === 'forgot') {
      forgotPassword(values.email, history);
    } else {
      console.log(values); // form values still populated
      onAuth(formType, values, history)
        .then(result => {
          console.log('result received'); // values empty
          setLoading(false);
            if (formType === 'signup') {
              history.push('/questionnaire')
            } else {
              history.push('/app')
            }
        })
        .catch(err => setLoading(false));
    }
  };

来自我的 redux actions.js 文件:

export function authUser(type, userData, history) {
  return dispatch => {
    dispatch(removeError());
    console.log('dispatch') // by this time the form values are empty
    // unless I comment out the dispatch(removeError()) above, 
    // in which case we still have values until 'token recevied' below
    return apiCall('post', `/users/${type}`, userData)
      .then(({ jwt, refresh_token, ...user }) => {
        console.log('token received')
        localStorage.setItem('jwtToken', jwt);
        localStorage.setItem('jwtTokenRefresh', refresh_token);
        dispatch(getUser(user.id));
      })
      .catch(err => {
        handleError(dispatch, err);
      });
  };
}

我还在我的 AuthForm 组件中记录值。结果是这样的:

编辑:看起来我的组件肯定正在卸载,但我仍然不清楚为什么,或者如何防止它。

我正在尝试记忆调度功能,但它似乎没有效果。

const dispatch = useDispatch();
  const onAuth = useCallback(
    (formType, values, history) => {
      dispatch(authUser(formType, values, history))
    },
    [dispatch]
  );

【问题讨论】:

  • 您的表单值处于本地状态,因此我认为当您调度某些操作时组件已卸载。如果事件处理程序正在提交表单,你也应该防止默认。
  • 有没有办法避免这种情况?这似乎是一个相当常见的用例,您希望保留本地状态但在 Redux 中更新某些内容。
  • 我的 handleSubmit() 函数中也有 e.preventDefalut()
  • 避免什么?如果状态重置是由组件重新安装引起的,那么您可以解除状态,将其放入 redux 或使用该状态的上下文。
  • 避免重新安装组件——没有理由这样做。状态处于适当的级别,因为它指的是 AuthForm.js 工作的表单

标签: javascript reactjs redux


【解决方案1】:

您的组件是 redux 存储的订阅者,这就是它重新渲染的原因, 组件的状态被初始化为初始状态, 现在您需要一种在渲染周期内保持这些组件状态的方法。 在类组件上,您可以将值绑定到实例,即使用 this.value == 'value' 以便在渲染之间保持相同,

在功能组件上,您可以使用一个名为 useRef 的钩子来实现这一点 除非您手动更改它,否则它不会在重新渲染时更改其值, 希望对你有帮助

【讨论】:

  • 要添加它,请使用 react 中的 memo() 来防止组件在其数据未更改时重新渲染
猜你喜欢
  • 2018-01-03
  • 1970-01-01
  • 2021-05-03
  • 1970-01-01
  • 1970-01-01
  • 2016-12-22
  • 1970-01-01
  • 2020-04-24
  • 1970-01-01
相关资源
最近更新 更多