【问题标题】:react-redux/react-router: how to change state on Linkreact-redux/react-router:如何更改 Link 上的状态
【发布时间】:2016-08-19 14:23:32
【问题描述】:

page A 上,我有一个 react-router <Link> 可以通向 page B。在 页面 B 上,我有一个按钮尝试在服务器上执行某些操作,并且要么导致 页面 C(成功)要么留在 页面 B(失败)。在最后一种情况下,页面上会出现一条消息以显示错误。

当我在页面 B 上看到错误消息时,如果我使用浏览器返回按钮返回 页面 A,然后再次单击 <Link> 继续页面B,消息还在。

所以使用 <Link> 时状态似乎没有重置,我想知道在 <Link> 上更改状态的好方法是什么?


编辑: 为了更清楚,在 page A 上,您有一个 <Link>page B。在页面 B,您有一个按钮来提交您的登录信息(登录名和密码)。

当您点击时,一个动作会向服务器发出请求:

function authRequest() {
  return {
    type: actionTypes.AUTH_REQUEST
  };
}

function authReceive(authToken) {
  return {
    type: actionTypes.AUTH_RECEIVE,
    authToken
  };
}

function authError(errors) {
  return {
    type: actionTypes.AUTH_ERROR,
    errors
  };
}

export function fetchLogin(email, password) {
  return function (dispatch) {
    dispatch(authRequest());
    const urlApi = `//${AUTH_BACKEND_HOST}:${AUTH_BACKEND_PORT}/${AUTH_BACKEND_URL.login}`
    fetch(urlApi, {
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'content-type': 'application/json'
      },
      body: JSON.stringify({
        email,
        password
      })
    })
    .then((response) => {
      if(response.ok) {
        response.json().then(function(json) {
          dispatch(authReceive(json.key));
          dispatch(push('/'));
        });
      } else {
        response.json().then(function(json) {
          dispatch(authError(JSON.stringify(json)));
        });
      }
    })
    .catch(function(ex) {
      console.log(ex);
    });
  };
}

...如果失败,一个reducer在状态中添加错误信息:

const initialState = {
  authToken: '',
  isFetching: false,
  errors: ''
}

export default function (state=initialState, action) {
  switch (action.type) {
    case actionType.AUTH_REQUEST:
      return {
        ...state,
        isFetching: true,
        errors: ''
      };
    case actionType.AUTH_RECEIVE:
      return authLogin(state, action);
    case actionType.AUTH_ERROR:
      return {
        ...state,
        errors: (JSON.parse(action.errors))
      };
  }
  return state;
}

function authLogin(state, action) {
  const { authToken } = action;
  return {
    ...state,
    isFetching: false,
    errors: '',
    authToken
  };
}

...最后,presenter 有一个带有 <p> 的渲染方法,如果它处于该状态,则会显示错误:

render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>Email <input ref="email" /></label>
        <label>Password <input ref="password" type="password" /></label><br />
        <p className="error">{this.props.errors.non_field_errors}</p>
        <button type="submit">Login</button>
      </form>
    )
  }

正如我所说,如果它显示错误,然后我返回 页面 A,然后通过单击链接再次返回 页面 B,消息仍然存在。

谢谢。

【问题讨论】:

  • 如果状态没有被重置,这意味着componentWillMountComponentB 没有被调用。包括您的路线配置,它将提供更好的想法
  • 你说得对,我正在开发的这个应用程序中没有 componentSomething 之类的功能。我在一些示例中看到了它们,但在此应用程序中没有使用它们,我仍然可以设法注册用户,然后在主页上连接和导航。

标签: reactjs react-router react-redux


【解决方案1】:

Redux 始终如一地、清晰地跟踪应用程序的状态,与使用该状态的组件无关。因此,故障状态保持不变也就不足为奇了,除非您专门清除它。

那么接下来的问题是,在什么情况下要清除失败状态呢? (什么情况下想忘记页面B的操作失败?)

  1. 从 A 到 B 关注 &lt;Link&gt; 时?您可以使用&lt;Link&gt;'s onClick 来执行此操作,但它似乎过于具体。 (如果用户通过其他方式到达 B 怎么办?为什么 A 的链接必须关心 B 的故障状态?)
  2. B 何时挂载? (换句话说,“每次我输入 B 时,都将其视为空白。”)要实现这一点,请使用 componentWillMount
  3. B 何时卸载? (换句话说,“每次我离开 B 时,丢弃 B 内任何操作的状态。”)要实现这一点,请使用 componentWillUnmount

我猜选项 2 或 3 最适合您的设计。因此,您将从componentWillMountcomponentWillUnmount 发送一个适当的操作,该操作的reducer 将清除任何失败状态。

【讨论】:

  • 谢谢,我会试试的,我看到有一些像 componentSomething 这样的函数,但我没有使用它。所以是的,我希望 B 每次我继续它时都是空白的。
  • 关于(3),我认为我们不需要在卸载时明确清除状态,react 会为我们这样做
  • @Deadfish - 我应该已经确认了术语。如果“状态”是指保存在 Redux 存储中的应用程序状态(这是我的假设),它的存在时间与 Redux 存储一样长(可能是整个应用程序)。如果他的意思是页面B的React组件状态,那么你是对的,当页面B的组件卸载时它被清除(并且在页面B组件安装时也被初始化,所以我认为这不会导致他的问题)。
  • @JoshKelley 是的,我说的是存储状态,而不是组件状态。我想...我编辑了我的问题。
猜你喜欢
  • 2021-11-05
  • 2017-08-12
  • 1970-01-01
  • 2016-01-17
  • 2018-01-29
  • 2017-05-19
  • 2019-08-09
  • 2022-10-04
  • 2018-09-04
相关资源
最近更新 更多