调用的 React Navigation 5 headerRight 按钮函数未获得更新状态

React Navigation 5 headerRight button function called doesn't get updated states

在下面的简化示例中,用户使用 TextInput 更新标签状态,然后单击 header 中的 'Save' 按钮。在提交函数中,当请求标签状态时,它 returns 原始值 '' 而不是更新后的值。

需要对导航进行哪些更改header右键以解决此问题?

注意:当“保存”按钮位于渲染视图中时,一切都按预期工作,只是当它位于 header 中时并非如此。

import React, {useState, useLayoutEffect} from 'react';
import { TouchableWithoutFeedback, View, Text, TextInput } from 'react-native';

export default function EditScreen({navigation}){
  const [label, setLabel] = useState('');

  useLayoutEffect(() => {
      navigation.setOptions({
        headerRight: () => (
          <TouchableWithoutFeedback onPress={submit}>
            <Text>Save</Text>
          </TouchableWithoutFeedback>
        ),
      });
    }, [navigation]);

  const submit = () => {
    //label doesn't return the updated state here
    const data = {label: label}
    fetch(....)
  }

  return(
    <View>
      <TextInput onChangeText={(text) => setLabel(text) } value={label} />  
    </View>
  )

}

标签应作为 useLayouteffect 的依赖项传递,这将使挂钩 运行 发生变化

  React.useLayoutEffect(() => {
      navigation.setOptions({
        headerRight: () => (
          <TouchableWithoutFeedback onPress={submit}>
            <Text>Save</Text>
          </TouchableWithoutFeedback>
        ),
      });
    }, [navigation,label]);

Guruparan 对这个问题的回答是正确的,尽管我想让该解决方案更适用于具有许多 TextInput 的屏幕。

为此,我添加了一个名为保存的附加状态,单击“完成”时该状态设置为 true。这会触发调用 useEffect 挂钩,从而触发提交。

export default function EditScreen({navigation}){
  const [label, setLabel] = useState('');
  const [saving, setSaving] = useState(false);

  useLayoutEffect(() => {
      navigation.setOptions({
        headerRight: () => (
          <TouchableWithoutFeedback onPress={() => setSaving(true)}>
            <Text>Done</Text>
          </TouchableWithoutFeedback>
        ),
      });
    }, [navigation]);

    useEffect(() => {
      // Check if saving to avoid calling submit on screen unmounting
      if(saving){
        submit()
      }
    }, [saving]);

    const submit = () => {
      const data = {label: label}
      fetch(....)
    }

    return(
      <View>
        <TextInput onChangeText={(text) => setLabel(text) } value={label} />  
      </View>
    )

}