Issue
My dev env is
"react": "17.0.1", "react-dom": "17.0.1", "react-hook-form": "^7.22.1", "react-native": "^0.64.3",
I'd like to refresh my page once I delete my comment.
Mostly in this case, I've used navigation.goBack()
or navigation.navigate("same page")
like below.
const onDeleteClick = () => {
deleteCommentMutation();
navigation.navigate("Comments");
};
But the problem is Comments page has Flatlist with data getting from the previous page. On this page, I can't pass same data set ({route}) to Comments page.
So It refreshes my page but with no data, which means empty page. I don't want that. I just refresh my page as deleting only one comment.
When I searched on Internet, people recommend window.location.reload()
But when I use it instead of navigation, it gives me error saying that:
TypeError: undefined is not an object (evaluating 'window.location.reload')
at node_modules/react-native/Libraries/Core/ExceptionsManager.js:104:6 in reportException
at node_modules/react-native/Libraries/Core/ExceptionsManager.js:172:19 in handleException
at node_modules/react-native/Libraries/Core/setUpErrorHandling.js:24:6 in handleError
at node_modules/expo-error-recovery/build/ErrorRecovery.fx.js:12:21 in ErrorUtils.setGlobalHandler$argument_0
Can't React native use window.location.reload()? As far as I know, It doesn't need any installation or import.
How can I use window.location.reload()? Otherwise, which way can I refresh my page?
Srimurugan Sri taught me that React can't use window ;) thanks. So as he recommended I tried to use extraData. as far as I understand, it watch any change on {data} part. And if some change detected, automatically re-render flatlist.
So I made useState
and added extraData
as below.
const [selectedId, setSelectedId] = useState(null);
return (
<Container>
<CommentBox>
<FlatList
keyboardDismissMode={true}
showsVerticalScrollIndicator={false}
data={route?.params?.comments}
keyExtractor={(comment) => "" + comment.id}
renderItem={renderComment}
extraData={selectedId}
/>
</CommentBox>
</Container>
);
But it still doesn't refresh my page. Can you teach me more?
CommentRow page
export default function CommentRow({
id,
user,
payload,
isMine,
createdAt,
updatedAt,
commentNumber,
photoId,
}) {
const createdDate = new Date(+createdAt);
const date = createdDate.toISOString().substring(0, 10);
const updateDeleteComment = (cache, result) => {
const {
data: {
deleteComment: { ok, error },
},
} = result;
if (ok) {
cache.evict({ id: `Comment:${id}` });
cache.modify({
id: `Photo:${photoId}`,
fields: {
commentNumber(prev) {
return prev - 1;
},
},
});
}
};
const [deleteCommentMutation] = useMutation(DELETE_COMMENT_MUTATION, {
variables: {
id,
},
update: updateDeleteComment,
});
const onDeleteClick = () => {
deleteCommentMutation();
};
return (
<Container>
<CommentContainer>
<UserImage source={{ uri: user.avatar }} />
<TextBox>
<Header>
<Username>{user.username}</Username>
<CreatedTime>{date}</CreatedTime>
</Header>
<CommentText>{payload}</CommentText>
</TextBox>
</CommentContainer>
{isMine ? (
<WriteContainer>
<TouchableOpacity>
<WriteComment>수정</WriteComment>
</TouchableOpacity>
<TouchableOpacity onPress={onDeleteClick}>
<WriteComment>삭제</WriteComment>
</TouchableOpacity>
</WriteContainer>
) : null}
</Container>
);
}
Solution
Unfortunately, there is no such concept as "reload" in React Native. Once a Route is "mounted" it won't remount even if you navigate from and back to the component.
So I use the following idea to "reload" the component once I navigate to it from another one and when I want to reload the component on the refresh pull gesture
export class Props {
refreshTimeStamp: string | undefined
};
export class MainParamList {
Main: Props
}
export default function ({
route,
navigation,
}: NativeStackScreenProps<MainParamList, 'Main'>) {
const [data, setData] = setState<string>('')
const refreshData = () => setData('result')
useEffect(() => {
if (route.params?.refreshTimeStamp) {
void refreshData();
}
}, [route.params]);
return (
<ScrollView
contentContainerStyle={{
flexGrow: 1,
backgroundColor: 'white',
}}
refreshControl: {
<RefreshControl
refreshing={false}
onRefresh={() => {
navigation.navigate('Main', { refreshTimeStamp: new
Date().toISOString() });
}}
style={{ flexGrow: 1 }}
/>
}
>
{data}
</ScrollView>
);
}
Answered By - Nikita Chernenko
Answer Checked By - - Clifford M. (ReactFix Volunteer)