React Native - 将回调传递给另一个屏幕

React Native - pass callback to another screen

我有一个带表格的屏幕。现在在该表单中有一个按钮可以打开另一个屏幕,用户可以在其中选择目标选项,并且在选择后他们将导航回原始表单(堆栈导航器),原因是用户还可以在那里创建一个新选项以便他们转到UI 与单独编辑选项(他们可以)时一样。

我下面的代码解决方案有效,但是我收到以下警告:

Non-serializable values were found in the navigation state. This can break usage such as persisting and restoring state. This might happen if you passed non-serializable values such as function, class instances etc. in params. If you need to use components with callbacks in your options, you can use 'navigation.setOptions' instead. See https://reactnavigation.org/docs/5.x/troubleshooting#i-get-the-warning-non-serializable-values-were-found-in-the-navigation-state for more details.

现在 link 建议使用 setOptions,但这更像是向 header 添加按钮,但事实并非如此,用户在目标屏幕中选择该选项通过点击选项。

以下是代码的重要部分:

// MAIN FORM SCREEN
<Button title={"Some Title"} onPress={openSelectItem}></Button>

const openSelectFish = () => {
    return navigation.navigate("ItemList", { sendItemBack: true, onGoBack: onSelectItem });
};

const onSelectItem = (item: ItemDTO) => {
    setItem(item.name); // basic useState
};

// THE OPTIONS SCREEN
const onChooseItem = (item: ItemDTO) => {
    console.log(this);
    if ((typeof route !== "object") || (typeof route.params !== "object")) return;
    if (!route.params.sendItemBack ?? true) return;
    route.params.onGoBack(item);
    return navigation.goBack();
};
// onChooseItem is then used in onPress of each option

是否有更好的方法将回调发送到另一个屏幕?

不建议通过route params传递回调函数。从您的代码和您的解释来看,您实际上想要 pass data back to the screen on goBack.

而不是做

route.params.onGoBack(item);
return navigation.goBack();

我们可以在 navigation.goBack() 上的路由参数中将 item 传回 MainFormScreen,并在 useEffect 中直接在 MainFormScreen 中设置状态。这使我们不必在路由参数中传递函数。相反,我们直接在表单中设置状态。

OptionsScreen 我们可以像往常一样使用 navigate 并将 item 传回 MainFormScreen 而不是调用 goBack

return navigation.navigate('MainFormScreen', { item: item })

MainFormScreen 在这里,我们不再传递一个函数,而是对路由参数的变化做出反应。

const openSelectFish = () => {
    return navigation.navigate("ItemList", { sendItemBack: true });
};

const params = useMemo(() => route.params || {}, [route.params])

const [item, setItem] = useState()

const onSelectItem = useCallback((item: ItemDTO) => {
    setItem(item.name); // basic useState
}, [setItem]);

useEffect(() => {
   onSelectItem(params.item)
}, [params, onSelectItem])