如何解决组件未在useState数组更改时重新呈现 console.log输出关注事项
我在FeedScreen.js
上显示的“ tweet”卡上有一个收藏夹按钮。
~~~~~~~~~ IMPORTS SNIP ~~~~~~~~~
function FeedScreen(props) {
const [feed,setFeed] = useState([]);
const [favorites,setFavorite] = useState([]);
const [refreshing,setRefreshing] = useState(false);
useEffect(() => {
loadFeed(0,4);
},[]);
const loadFeed = async (last_id = 0,limit = 1) => {
setRefreshing(true);
const response = await tweetsApi.getTweets(last_id,limit);
if (response.ok) {
setFeed(response.data["data"].concat(feed));
} else {
console.log(response.problem);
}
setRefreshing(false);
};
const handleBookmark = async (item_id) => {
const response = await tweetsApi.toggleBookmark(item_id);
if (response.ok) {
console.log("ok response");
setFavorite(favorites.concat(item_id));
// I've tried this as well
// setFavorite([...favorites].concat(item_id));
// but in vain
console.log(favorites);
}
};
return (
<Screen style={styles.screen}>
<FlatList
data={feed}
keyExtractor={(tweet) => {
return tweet.id.toString();
}}
renderItem={({ item }) => (
~~~~~~~~~ SNIP ~~~~~~~~~
<CardFooter
style={{ marginLeft: 20 }}
item={item}
onPress={handleBookmark}
/>
</View>
)}
ItemSeparatorComponent={ListItemSeparator}
refreshing={refreshing}
onRefresh={() => {
loadFeed(feed[0]["id"],2);
}}
/>
</Screen>
);
}
~~~~~~~~~ SNIP ~~~~~~~~~
这是CardFooter.js
:
~~~~~~~~~ SNIP ~~~~~~~~~
function CardFooter({ item,onPress }) {
return (
<View style={styles.bookmark}>
<TouchableOpacity
onPress={() => {
return onPress(item.id);
}}
>
{item.bookmarked && (
<FontAwesome name="bookmark" size={24} color="red" />
)}
{!item.bookmarked && (
<FontAwesome5 name="bookmark" size={24} color="black" />
)}
</TouchableOpacity>
</View>
</View>
);
}
export default CardFooter;
~~~~~~~~~ SNIP ~~~~~~~~~
但是该组件似乎没有重新呈现。 我看过这些:
- react-component-not-re-rendering-after-using-usestate-hook
- 类似的here
- Another one 17 days back - why-usestate-is-not-re-rendering
- usestate-not-re-rendering-when-updating-nested-object
所有这些以及其他类似的东西,每个都指向一个事实,即应该创建一个新数组,以便react重新渲染它。
更新
console.log输出
是,console.log
正在打印数组,尽管先前是一个值。这是因为useState
是异步的,因此它没有打印实时数组。因此,当第二次调用此方法时,它将显示一个item_id
(上一个)添加到favorites
解决方法
我最后通过管理组件本身中的状态解决了这个问题。
不确定这是否是执行此操作的“正确方法”,但请阅读here (how-to-add-a-simple-toggle-function-in-react-native) ,这是您可以执行此操作的方式。
因此,现在书签组件从顶级组件(FeedScreen.js
)获得响应:
const handleBookmark = async (item_id) => {
const response = await tweetsApi.toggleBookmark(item_id);
if (response.ok) {
return true;
} else {
return false;
}
};
并更改CardFooter.js
,即书签组件所在的位置。
function CardFooter({ item,onPress }) {
const [favorite,setFavorite] = useState(item.bookmarked);
return (
<View style={styles.bookmark}>
<TouchableOpacity
onPress={async () => {
let response = await onPress(item.id);
if (response) {
setFavorite(!favorite);
} else {
alert("Some error occurred");
}
}}
>
{favorite && <FontAwesome name="bookmark" size={24} color="red" />}
{!favorite && (
<FontAwesome5 name="bookmark" size={24} color="black" />
)}
</TouchableOpacity>
</View>
</View>
);
}
关注事项
我有点担心如何处理此组件中的响应。
我应该在底部组件中处理async
操作吗?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。