英文:
Passing screen-defined function to header triggering "Non-serializable" issue
问题
我在一个堆栈导航器中有一个屏幕,在其中我已经定义了全局标题栏,包含一个按钮,该按钮将触发一个模态框。我遇到的问题是,我正在在屏幕组件内部定义触发模态框的函数,并尝试通过navigation.setParams
传递函数,但我遇到了警告:
> 在导航状态中找到了不可序列化的值
const ViewB = ({ route, navigation }) => {
const [showModal, setShowModal] = useState(false);
useEffect(() => {
navigation.setParams({showModal: () => setShowModal(true)});
}, []);
<Stack.Screen name="ViewB" component={ViewB} options={({ route }) => ({
headerRight: () => (
<View>
<Button onPress={() => {
showModal = route?.params?.["showModal"];
showModal && showModal();
}} title="Toggle modal" />
</View>
)
})} />
在Google搜索之后,我找到了官方文档上关于这个问题的信息,还有这个 SO 问题/答案解释了RN不喜欢我们将函数传递给navigation
,因为如果事情发生变化等等,它可能会破坏功能... 但是我不确定有没有更好的方法来解决这个问题。
有没有一种方法可以在不引起React Native不适的情况下实现我期望的结果?
英文:
I have a stack navigator in which one of my screens, I have defined the global header bar to contain a button that will trigger a modal. The issue I have is that I am defining the function to trigger said modal from within the screen component itself and attempting to pass the function via navigation.setParams
and I am facing the warning:
> Non-serializable values were found in the navigation state
const ViewB = ({ route, navigation }) => {
const [showModal, setShowModal] = useState(false);
useEffect(() => {
navigation.setParams({showModal: () => setShowModal(true)});
}, []);
<Stack.Screen name="ViewB" component={ViewB} options={({ route }) => ({
headerRight: () => (
<View>
<Button onPress={() => {
showModal = route?.params?.["showModal"];
showModal && showModal();
}} title="Toggle modal" />
</View>
)
})} />
After Googling I did come across the official docs on the issue and also this SO question/answer that explained that RN doesn't like us passing functions to navigation
as it could potentially break functionality down the line if things change etc... however I'm unsure of a better way to go about this.
Is there a way in which I can achieve my desired result without upsetting react-native?
答案1
得分: 1
是的,react-navigation 不允许我们将方法传递给导航 props。
根据您的要求,无需将方法传递给父级参数。
您可以通过在屏幕代码中添加 headerRight 来实现这一点,请查看以下代码更好地理解。
const ViewB = ({ route, navigation }) => {
const [showModal, setShowModal] = useState(false);
useLayoutEffect(() => {
navigation.setOptions({
headerRight: () => (
<View>
<Button
onPress={() => {
setShowModal(true);
}}
title="Toggle modal"
/>
</View>
),
});
}, [navigation]);
const onBackPress = () => {
navigation.navigate(route.params.previousScreen, {
val: 5,
val2: 6,
});
};
return (
<View>
<Text>ViewB</Text>
<Text>Params: {JSON.stringify(route.params)}</Text>
<Button title="back" onPress={onBackPress} />
{showModal && <Modal onClose={() => setShowModal(false)} />}
</View>
);
};
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator mode="modal">
<Stack.Screen name="ViewA" component={ViewA} />
<Stack.Screen name="ViewB" component={ViewB} />
</Stack.Navigator>
</NavigationContainer>
);
}
请注意,我只翻译了代码部分,没有包括其他内容。
英文:
Yes, react-navigation doesn't allow us to pass the methods in navigation props.
As per your requirement there is no need to pass the method in the params to the parent.
you can achieve this by adding the headerRight inside your screen code, checkout the below code changes for better understanding.
const ViewB = ({route, navigation}) => {
const [showModal, setShowModal] = useState(false);
useLayoutEffect(() => {
navigation.setOptions({
headerRight: () => (
<View>
<Button
onPress={() => {
setShowModal(true);
}}
title="Toggle modal"
/>
</View>
),
});
}, [navigation]);
const onBackPress = () => {
navigation.navigate(route.params.previousScreen, {
val: 5,
val2: 6,
});
};
return (
<View>
<Text>ViewB</Text>
<Text>Params: {JSON.stringify(route.params)}</Text>
<Button title="back" onPress={onBackPress} />
{showModal && <Modal onClose={() => setShowModal(false)} />}
</View>
);
};
export default function App() {
return (
<NavigationContainer>
<Stack.Navigator mode="modal">
<Stack.Screen name="ViewA" component={ViewA} />
<Stack.Screen name="ViewB" component={ViewB} />
</Stack.Navigator>
</NavigationContainer>
);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论