react-native - 如何反应原生重新渲染 Flatlist?
问题描述
如何反应原生重新渲染 Flatlist?
使用 Effect 检查 tagId 的数据并打开一个新页面,直到 tagId 存在。
使用 use Effect 导入的数据不会传递给 renderItem,而只会传递第一页的数据。
如何将更新的数据从 useEffect 转发到 renderItem?
app.tsx
const App: () => Node = () => {
const Stack = createNativeStackNavigator();
const [accessToken, setAccessToken] = useState("");
const [isSearchHidden, setIsSearchHidden] = useState(false);
const [isHomeHidden, setIsHomeHidden] = useState(false);
const [id, setId] = useState("");
const [tagId, setTagId] = useState("");
const [chargeAmount, setChargeAmount] = useState("");
const value = {
setAccessToken: setAccessToken,
isSearchHidden: isSearchHidden,
setIsSearchHidden: setIsSearchHidden,
isHomeHidden: isHomeHidden,
setIsHomeHidden: setIsHomeHidden,
id: id,
setId: setId,
tagId: tagId,
setTagId: setTagId,
chargeAmount: chargeAmount,
setChargeAmount: setChargeAmount,
};
useEffect(() => {
AsyncStorage.getItem("@user", (_: any, result: any) => {
// console.log("user: ",result)
if (result) {
// result가 있을때만 accessToken 저장
setAccessToken(result);
}
});
}, []);
const errorLink = onError(({ graphQLErrors, operation, forward }) => {
if (graphQLErrors) {
for (const err of graphQLErrors) {
if (err.extensions?.code === "UNAUTHENTICATED") {
operation.setContext({
headers: {
...operation.getContext().headers,
authorization: `Bearer ${getAccessToken(setAccessToken)}`,
},
});
return forward(operation);
}
}
}
});
const uploadLink = createUploadLink({
uri: "https://backend03-team.codebootcamp.co.kr/team05",
headers: {
authorization: `Bearer ${accessToken}`,
},
credentials: "include",
});
const client = new ApolloClient({
cache: new InMemoryCache(),
link: ApolloLink.from([errorLink, uploadLink as unknown as ApolloLink]),
});
return (
<GlobalContext.Provider value={value}>
<ApolloProvider client={client}>
<NavigationContainer>
<Stack.Navigator screenOptions={{ headerShown: false }}>
{accessToken ? (
<Stack.Screen name="tabNavigator" component={TabNavigator} />
) : (
<Stack.Screen name="Login" component={LoginNavigator} />
)}
</Stack.Navigator>
</NavigationContainer>
</ApolloProvider>
</GlobalContext.Provider>
);
};
export default App;
container
const ListContainer = () => {
const [aaa, setAaa] = useState(1);
const { data, fetchMore, refetch } = useQuery(FETCH_USED_ITEMS, {
variables: {
page: 1,
isSoldout: false,
},
});
useEffect(() => {
console.log("9999", data);
const result = data?.fetchUseditems.some((el) => {
return el.tags[0] === tagId;
});
console.log("33332232111", result);
console.log("989898", tagId);
if (result === false) {
onLoadMore();
} else {
return;
}
console.log("443432", aaa);
}, [data?.fetchUseditems]);
const { setId, id, setTagId, tagId } = useContext(GlobalContext);
const onPressDetail = (el) => {
setId(el._id);
console.log("555", el._id);
console.log("433", id);
};
const onPressListCategory = (value) => {
setTagId(value);
};
const onLoadMore = () => {
// if (!data) {
// return;
// }
fetchMore({
variables: {
page: Math.ceil(data?.fetchUseditems.length / 10) + 1,
},
updateQuery: (prev, { fetchMoreResult }) => {
return {
fetchUseditems: [
...prev.fetchUseditems,
...fetchMoreResult.fetchUseditems,
],
};
},
});
};
return (
<ListUI
data={data}
onPressDetail={onPressDetail}
onPressListCategory={onPressListCategory}
onLoadMore={onLoadMore}
setAaa={setAaa}
aaa={aaa}
fetchMore={fetchMore}
refetch={refetch}
/>
);
};
presenter
const ListUI = (props) => {
const { tagId, setTagId, setAaa } = useContext(GlobalContext);
const navigation = useNavigation();
const renderItem = ({ item }: any) => {
console.log("***********************", item);
return (
<>
{item.tags[0]?.includes(tagId) && (
<DetailProductWrapper key={item._id}>
<ProductImageWrapper
onPress={() =>
navigation.navigate("상품 상세보기", {
id: props.onPressDetail(item),
})
}
>
<ProductImage
source={{
uri: `https://storage.googleapis.com/${item.images[0]}`,
}}
/>
</ProductImageWrapper>
<InfoWrapper>
<InfoTextWrapper>
<InfoTitle>{item.name}</InfoTitle>
<InfoPrice>{item.price}원</InfoPrice>
</InfoTextWrapper>
<InfoFavoriteImage
source={require("../../../public/images/list/infofavorite.png")}
/>
</InfoWrapper>
</DetailProductWrapper>
)}
</>
);
};
console.log("================", props.data);
console.log("6666", props.aaa);
return (
<ListView>
<HeaderAnimation onPressListCategory={props.onPressListCategory} />
<FlatList
data={props.data?.fetchUseditems}
renderItem={renderItem}
keyExtractor={(item) => item.id}
onEndReached={props.onLoadMore}
extraData={props.data}
onEndReachedThreshold={0.8}
></FlatList>
</ListView>
);
};
数据控制台捕获 在此处输入图像描述
renderItem 控制台捕获 在此处输入图像描述
解决方案
通过将 extraData={this.state} 传递给 FlatList,我们确保 FlatList 本身会在状态更改时重新渲染。如果不设置这个 prop,FlatList 将不知道它需要重新渲染任何项目,因为它是一个 PureComponent,并且 prop 比较不会显示任何更改。
推荐阅读
- unit-testing - Golang unittest http 处理程序
- angular - 使用 Angular 6 Table/Grid 和 web api 的服务器端分页
- java - 以递归方式打印 (char) A 到 (n)
- vba - VBA 可以访问 Word 文档中 settings.xml.res 中的数据吗?
- pyspark - Pyspark 半正弦距离
- mql5 - MQL5 - 传递指标作为参数
- ubuntu - Gitlab 导出:找不到 Gemfile 或 .bundle / 目录
- c - C 在 scanf() 处无限循环
- groovy - 为什么 File 类 getAbsoluteFile 和 getParentFile 似乎没有正确返回值?
- r - 如何将小时数转换为时间?