Redux - 选择器失败时调度异步操作

时间:2017-07-20 09:18:00

标签: reactjs asynchronous redux action selector

我有以下连接组件:

const selectFullNameById = (state, id) =>
{
    const user = state.domain.people.values.find(u => u.id === id)
    return `${user.lastName} ${user.firstName}`
}

const mapStateToProps = (state, ownProps) => {

    const files = ownProps.files.map(f => ({
        ...f,
        fullName: selectFullNameById(state, f.creatorId)
    }))

    return {
        ...ownProps,
        files
    }
}

export default connect(mapStateToProps)(Uploader)

连接组件接收带有对象文字的数组作为Prop称为文件。每个对象文字都有一个creatorId值,我想传递给我的演示组件这个人的全名,所以我使用选择器“selectFullNameById”来获取这些值。当此人在全局状态下实际可用时,此方法有效。

但可能是这个人对象文字还没有出现在全局状态中,因此应该对服务器进行提取以检查他的名字是什么。所以我有一个异步动作创建器来进行查找。但我不知道如何从选择器中发送它。

1 个答案:

答案 0 :(得分:0)

我会做以下事情:

//1. create a default state for a person:

const DEFAULT_PERSON = { 
  id: -1,
  fullName: 'n/a',
  …
} //some useful stuff

//2. modify electFullNameById to

const selectFullNameById = (state, id) => {
  const user = state.domain.people.values.find(u => u.id === id) || null;
  //return default data, if user does not exist
  return (user === null) ?
    Object.assign({}, DEFAULT_PERSON).fullName :
    `${user.lastName} ${user.firstName}`
}

//3. refactor mapStateToProps to:

const mapStateToProps = (state, ownProps) => {

  const files = ownProps.files.map(f => ({
      ...f,
      fullName: selectFullNameById(state, f.creatorId)
  }))

  //no need to add the ownProps here
  return { files }
}

所以基本的想法是:创建一些有用的默认数据,用于未找到用户的情况。这样,在以下数据使用方面,您不会收到任何“未定义”错误。

如果可以像这样添加未定义的用户(假设您正在使用redux thunk和fetch),则调度异步操作:

const loadUser = uid => dispatch => fetch(`${url}/${uid}`)
  .then(response => response.json())
  .then(json => dispatch({
    type: 'user/loaded',
    payload: { user: json }
  }));

const YourComponent = ({ users, loadUser}) => {
  return (
    <div>
    {
      user.map(user => {
        if (!user loaded) loadUser(user.id);
        return (<some>html based on default data</html>)
      })
    }
    </div>
  );
}

您可以在渲染时立即调度操作,因为此操作是异步的,因此不会立即调用组件的重新呈现,这会导致递归。如果有许多用户需要加载,最好将其过滤掉并立即加载。