如何在 React Native 中将 promise 中的值传递给组件 prop?
How do I pass a value from a promise to a component prop in react native?
编辑:我不明白投反对票的原因,这是一个很好的问题,该站点上没有其他问题可以解决我的问题。我只是简单地预加载了数据来解决我的问题,但是如果不使用功能组件仍然无法解决问题。
我正在尝试将用户最后一条消息传递到 ListItem 字幕道具中,但我似乎无法找到 return 来自 promise/then 调用的值的方法。它是 return 一个承诺,而不是给我一个 "failed prop type" 的价值。我考虑过使用状态,但后来我认为我不能再调用 ListItem 组件内的函数了。
getMsg = id => {
const m = fireStoreDB
.getUserLastMessage(fireStoreDB.getUID, id)
.then(msg => {
return msg;
});
return m;
};
renderItem = ({ item }) => (
<ListItem
onPress={() => {
this.props.navigation.navigate('Chat', {
userTo: item.id,
UserToUsername: item.username
});
}}
title={item.username}
subtitle={this.getMsg(item.id)} // failed prop type
bottomDivider
chevron
/>
);
如果 ListItem
希望看到其 subtitle
属性 的承诺,你只能这样做,我猜它不会。 ;-)(猜测是因为我还没有玩过 React Native。React,但不是 React Native。)
相反,组件需要有两种状态:
- 字幕尚未加载
- 字幕已加载
...并渲染每个状态。如果你不希望组件有状态,那么你需要在父组件中处理异步查询,只有当你有它需要的信息时才渲染 this 组件。
如果 'last message' 仅特定于 ListItem
组件而不是您手头已有的东西,您可能希望让列表项自行发出网络请求。我会将函数移到 ListItem
中。您需要设置一些状态来保存此值,并可能进行一些条件渲染。然后你需要在挂载组件时调用这个函数。我假设您正在使用功能组件,所以 useEffect()
应该可以帮助您:
//put this is a library of custom hooks you may want to use
// this in other places
const useIsMounted = () => {
const isMounted = useRef(false);
useEffect(() => {
isMounted.current = true;
return () => (isMounted.current = false);
}, []);
return isMounted;
};
const ListItem = ({
title,
bottomDivider,
chevron,
onPress,
id, //hae to pass id to ListItem
}) => {
const [lastMessage, setLastMessage] = useState(null);
const isMounted = useIsMounted();
React.useEffect(() => {
async function get() {
const m = await fireStoreDB.getUserLastMessage(
fireStoreDB.getUID,
id
);
//before setting state check if component is still mounted
if (isMounted.current) {
setLastMessage(m);
}
}
get();
}, [id, isMounted]);
return lastMessage ? <Text>DO SOMETHING</Text> : null;
};
我通过在 componentDidMount 上的另一个 promise 方法中使用该 promise 方法解决了这个问题,并将用户的最后一条消息添加为所有用户的额外字段。这样我就可以让所有用户信息处于一种状态以填充 ListItem。
componentDidMount() {
fireStoreDB
.getAllUsersExceptCurrent()
.then(users =>
Promise.all(
users.map(({ id, username }) =>
fireStoreDB
.getUserLastMessage(fireStoreDB.getUID, id)
.then(message => ({ id, username, message }))
)
)
)
.then(usersInfo => {
this.setState({ usersInfo });
});
}
renderItem = ({ item }) => (
<ListItem
onPress={() => {
this.props.navigation.navigate('Chat', {
userTo: item.id,
UserToUsername: item.username
});
}}
title={item.username}
subtitle={item.message}
bottomDivider
chevron
/>
);
编辑:我不明白投反对票的原因,这是一个很好的问题,该站点上没有其他问题可以解决我的问题。我只是简单地预加载了数据来解决我的问题,但是如果不使用功能组件仍然无法解决问题。
我正在尝试将用户最后一条消息传递到 ListItem 字幕道具中,但我似乎无法找到 return 来自 promise/then 调用的值的方法。它是 return 一个承诺,而不是给我一个 "failed prop type" 的价值。我考虑过使用状态,但后来我认为我不能再调用 ListItem 组件内的函数了。
getMsg = id => {
const m = fireStoreDB
.getUserLastMessage(fireStoreDB.getUID, id)
.then(msg => {
return msg;
});
return m;
};
renderItem = ({ item }) => (
<ListItem
onPress={() => {
this.props.navigation.navigate('Chat', {
userTo: item.id,
UserToUsername: item.username
});
}}
title={item.username}
subtitle={this.getMsg(item.id)} // failed prop type
bottomDivider
chevron
/>
);
如果 ListItem
希望看到其 subtitle
属性 的承诺,你只能这样做,我猜它不会。 ;-)(猜测是因为我还没有玩过 React Native。React,但不是 React Native。)
相反,组件需要有两种状态:
- 字幕尚未加载
- 字幕已加载
...并渲染每个状态。如果你不希望组件有状态,那么你需要在父组件中处理异步查询,只有当你有它需要的信息时才渲染 this 组件。
如果 'last message' 仅特定于 ListItem
组件而不是您手头已有的东西,您可能希望让列表项自行发出网络请求。我会将函数移到 ListItem
中。您需要设置一些状态来保存此值,并可能进行一些条件渲染。然后你需要在挂载组件时调用这个函数。我假设您正在使用功能组件,所以 useEffect()
应该可以帮助您:
//put this is a library of custom hooks you may want to use
// this in other places
const useIsMounted = () => {
const isMounted = useRef(false);
useEffect(() => {
isMounted.current = true;
return () => (isMounted.current = false);
}, []);
return isMounted;
};
const ListItem = ({
title,
bottomDivider,
chevron,
onPress,
id, //hae to pass id to ListItem
}) => {
const [lastMessage, setLastMessage] = useState(null);
const isMounted = useIsMounted();
React.useEffect(() => {
async function get() {
const m = await fireStoreDB.getUserLastMessage(
fireStoreDB.getUID,
id
);
//before setting state check if component is still mounted
if (isMounted.current) {
setLastMessage(m);
}
}
get();
}, [id, isMounted]);
return lastMessage ? <Text>DO SOMETHING</Text> : null;
};
我通过在 componentDidMount 上的另一个 promise 方法中使用该 promise 方法解决了这个问题,并将用户的最后一条消息添加为所有用户的额外字段。这样我就可以让所有用户信息处于一种状态以填充 ListItem。
componentDidMount() {
fireStoreDB
.getAllUsersExceptCurrent()
.then(users =>
Promise.all(
users.map(({ id, username }) =>
fireStoreDB
.getUserLastMessage(fireStoreDB.getUID, id)
.then(message => ({ id, username, message }))
)
)
)
.then(usersInfo => {
this.setState({ usersInfo });
});
}
renderItem = ({ item }) => (
<ListItem
onPress={() => {
this.props.navigation.navigate('Chat', {
userTo: item.id,
UserToUsername: item.username
});
}}
title={item.username}
subtitle={item.message}
bottomDivider
chevron
/>
);