我的开发环境是
“反应”:“17.0.1”, “反应-dom”:“17.0.1”, "react-hook-form": "^7.22.1", “反应本机”:“^0.64.3”,
删除评论后我想刷新我的页面。 大多数情况下,我使用了
navigation.goBack()
或 navigation.navigate("same page")
,如下所示。
const onDeleteClick = () => {
deleteCommentMutation();
navigation.navigate("Comments");
};
但问题是评论页面有 Flatlist,其中的数据是从上一页获取的。 在此页面上,我无法将相同的数据集({route})传递到评论页面。
所以它刷新了我的页面,但没有数据,这意味着空页面。 我不想要这样。我只是刷新页面,只删除一条评论。
我在网上搜索时,人们推荐
window.location.reload()
但是当我使用它而不是导航时,它会给我错误提示:
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
React原生不能使用window.location.reload()吗? 据我所知,它不需要任何安装或导入。
如何使用window.location.reload()? 否则,我可以通过什么方式刷新我的页面?
Srimurugan Sri 教我 React 不能使用窗口;)谢谢。 因此,按照他的建议,我尝试使用 extraData。 据我了解,它会观察 {data} 部分的任何变化。 如果检测到某些更改,则会自动重新渲染平面列表。
所以我制作了
useState
并添加了extraData
,如下所示。
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>
);
但它仍然没有刷新我的页面。 你能教我更多吗?
评论行页面
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>
);
}
如果你想刷新Flatlist的数据,你可以使用FlatList组件上的extraData属性而不是改变路由。
我们不能在 React Native 中使用
window.location.reload()
。
不幸的是,React Native 中没有“重新加载”这样的概念。一旦“安装”了路线,即使您往返于组件,它也不会重新安装。
因此,当我从另一个组件导航到该组件时,以及当我想通过刷新拉动手势重新加载该组件时,我使用以下想法来“重新加载”该组件
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>
);
}
因为您的数据来源来自
route.params.comments
。 Flatlist 不会刷新数据,因为您有 extraData 作为 SelectedID。
请保存您的数据状态并将相同的状态传递给 extraData。
import React,{useState, useEffect} from 'react';
useEffect( () => {
const [comments, setComments] = useState(route?.params?.comments);
// update the comments after deleting using setComments() syntax;
},[])
//Both data & extraData is comments
const [selectedId, setSelectedId] = useState(null);
return (
<Container>
<CommentBox>
<FlatList
keyboardDismissMode={true}
showsVerticalScrollIndicator={false}
data={comments}
keyExtractor={(comment) => "" + comment.id}
renderItem={renderComment}
extraData={comments}
/>
</CommentBox>
</Container>
);
// You cannot use window.location.reload() in react native, but you can use in Web development
我不知道你为什么这样做(反应是反应式框架,所以使用它),但你可以将道具传递到你的屏幕
navigation.navigate('Comments', {setData: setData, data: data});
数据 => 评论只是名称
然后在你的“评论”(CommentsScreen)中,只需从路由参数中调用“setData”,如
interface CommentsScreenRouteProps {
key: string,
name: string,
params: {
data,
setData: React.Dispatch<any>,
},
path: string,
}
...
const route = useRoute<CommentsScreenRouteProps>();
...
route.params.setData(route.params.data.filter(() => true))
我的示例可能只有两个问题,但第一个可以修复,第二个被忽略
如果您确实想在屏幕上强制重新渲染,可以使用的一种方法是使用 useFocusEffect 钩子。每次屏幕获得焦点时它都会触发。
在OP的情况下,听起来好像要求在用户仍在屏幕上时重新渲染当前屏幕。在这种情况下,您可以更新状态项以强制重新渲染。状态项本身不必显示在屏幕上的任何位置:
const [dummyState, setDummyState] = useState(0);
// Connect this function to the onPress prop of a Button as an example.
// For the OP's case, you could add it into the code that deletes the comment,
// directly after the comment is deleted.
function btnHandler() {
// This will force a re-render.
setDummyState(Date.now());
}
正如其他人所指出的,通常不建议强制重新渲染,但如果您确实有特殊情况确实想要重新渲染,则可以使用其中一种技术来完成工作。