我有以下连接组件:
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”来获取这些值。当此人在全局状态下实际可用时,此方法有效。
但可能是这个人对象文字还没有出现在全局状态中,因此应该对服务器进行提取以检查他的名字是什么。所以我有一个异步动作创建器来进行查找。但我不知道如何从选择器中发送它。
答案 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>
);
}
您可以在渲染时立即调度操作,因为此操作是异步的,因此不会立即调用组件的重新呈现,这会导致递归。如果有许多用户需要加载,最好将其过滤掉并立即加载。