我在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重新渲染它。
是,console.log
正在打印数组,尽管先前是一个值。这是因为useState
是异步的,因此它没有打印实时数组。因此,当第二次调用此方法时,它将显示一个item_id
(上一个)添加到favorites
答案 0 :(得分:0)
我最后通过管理组件本身中的状态解决了这个问题。
不确定这是否是执行此操作的“正确方法”,但请阅读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
操作吗?