React Native useEffect未在状态更新时激发

uyhoqukh  于 2023-01-27  发布在  React
关注(0)|答案(3)|浏览(139)

我在react原生组件中用useState()更新了一些状态,一旦我设置了状态,我想把细节保存到服务器,所以我在useEffect()钩子中设置了它,为了清楚起见,状态的设置是有效的,我看到值打印到屏幕上。
然而,我注意到的是,即使我在useEffect()钩子的dependency数组中将note设置为依赖项,当状态更新时,函数也不会触发。

const [note, setNote] = useState('');
  const dispatch = useDispatch();
  useEffect(() => {
    if (note) {
      console.log('updating note...');
      dispatch(updateNote(props.client.id, note));
    }
  }, [note]);

仅供参考,我正在更新TextInput内部的状态,如下所示(我不得不使用onBlur来避免因在TabNavigator的screenOptions内传递组件而导致第一个字符类型上的react焦点丢失的问题):

<TextInput
  key='note'
  style={{
    color: '#fff',
    fontSize: 16,
    width: '100%',
    textAlign: 'center',
  }}
  placeholder='Tap here to share something...'
  placeholderTextColor={styles.colors.textPlaceholder}
  maxLength={50}
  onBlur={(text) => setNote(text)}
  defaultValue={note || props?.client?.note?.value}
/>

正如我提到的,这是一个棘手的情况,因为当我依赖onChangeText()onChange()时,我必须避开react的焦点丢失。我将CustomHeader(父函数中的一个函数)传递给screenOptions中的TabNavigator,如下所示:

screenOptions={{
    headerShown: true,
    headerStyle: {
      backgroundColor: Colors.primary,
      elevation: 0,
      shadowOpacity: 0,
      shadowColor: 'transparent',
      height: 170,
    },
    key: 'patient-tab',
    headerShadowVisible: false,
    tabBarStyle: { backgroundColor: Colors.primary },
    headerTintColor: Colors.light,
    headerTitle: (props) => <CustomHeader {...props} />, // Passed in here
    tabBarActiveTintColor: Colors.light,
    tabBarInactiveTintColor: Colors.lightInactive,
    tabBarActiveBackgroundColor: Colors.primary,
    tabBarInactiveBackgroundColor: Colors.primary,
  }}

完整的代码如下所示:

export const ClientBottomTabNavigator = (props) => {
  const [note, setNote] = useState('');
  const dispatch = useDispatch();
  useEffect(() => {
    if (props.client.id && note) {
      console.log('updating note...');
      dispatch(updateNote(props.client.id, note));
    }
  }, [props.client.id, note]);

  const CustomHeader = () => {
    return (
      <View>
        <View style={{ width: '100%', flexDirection: 'row', justifyContent: 'space-between', marginBottom: 6 }}>
          <Feather
            name='chevron-left'
            size={24}
            onPress={() => props.navigation.goBack()}
            color={styles.colors.textInverse}
            style={{ justifySelf: 'flex-start', alignSelf: 'flex-start', width: '32%', marginBottom: 6 }}
          />
          <Text
            style={{
              color: '#fff',
              fontSize: 18,
              alignSelf: 'center',
              justifySelf: 'center',
              fontWeight: 'bold',
            }}
          >
            {props?.client?.firstName} {props?.client?.lastName}
          </Text>
          <Feather
            name='' // Leave this blank
            style={{ justifySelf: 'flex-end', alignSelf: 'flex-end', width: '32%' }}
          />
        </View>

        <View style={{ alignItems: 'center', marginBottom: 6 }}>
          <Text style={{ color: '#fff', fontSize: 18, marginBottom: 6 }}>
            {convertDiscipline(props?.client?.discipline)}
          </Text>
          <View>
            <TextInput
              key='note'
              style={{
                color: '#fff',
                fontSize: 16,
                width: '100%',
                textAlign: 'center',
              }}
              placeholder='Tap here to share something…’
              placeholderTextColor={styles.colors.textPlaceholder}
              maxLength={50}
              onBlur={(text) => setNote(text)}
              defaultValue={note || props?.client?.note?.value}
            />
          </View>
        </View>
      </View>
    );
  };

  const Tab = createBottomTabNavigator();
  return (
    <Tab.Navigator
      screenOptions={{
        headerShown: true,
        headerStyle: {
          backgroundColor: Colors.primary,
          elevation: 0,
          shadowOpacity: 0,
          shadowColor: 'transparent',
          height: 170,
        },
        key: 'client-tab',
        headerShadowVisible: false,
        tabBarStyle: { backgroundColor: Colors.primary },
        headerTintColor: Colors.light,
        headerTitle: (props) => <CustomHeader {...props} />, // Passed in here
        tabBarActiveTintColor: Colors.light,
        tabBarInactiveTintColor: Colors.lightInactive,
        tabBarActiveBackgroundColor: Colors.primary,
        tabBarInactiveBackgroundColor: Colors.primary,
      }}
      initialRouteName={'Visits'}
    >
      <Tab.Screen
        name='Visits'
        component={VisitsTab}
        options={{
          tabBarLabel: 'VISITS',
          tabBarIcon: ({ color, size }) => <FontAwesome name='street-view' color={color} size={size} />,
        }}
      />
      <Tab.Screen
        name='Chart'
        component={ChartTab}
        options={{
          tabBarLabel: 'CHARTS',
          tabBarIcon: ({ color, size }) => <FontAwesome name='id-badge' color={color} size={size} />,
        }}
      />
      <Tab.Screen
        name='Goals'
        component={GoalsTab}
        options={{
          tabBarLabel: 'EDIT GOALS',
          tabBarIcon: ({ color, size }) => <FontAwesome name='trophy' color={color} size={size} />,
        }}
      />
    </Tab.Navigator>
  );
};
rvpgvaaj

rvpgvaaj1#

onBlur={(text) => setNote(text)}

问题是,处理程序的参数不是input的值,它是一个合成的React事件,应该是

onBlur={(event => setNote(event.target.value)}

工作示例:https://stackblitz.com/edit/react-ts-wqr9dg?file=App.tsx

nnsrf1az

nnsrf1az2#

看这里https://playcode.io/1106437,它工作,但是你有onBlur,你需要模糊来触发动作,也许你需要使用onChangeText。

gk7wooem

gk7wooem3#

我发现您没有使用onChangeText,这会导致重新呈现,然后从TextInput组件丢失焦点。
使用onBlur方法将永远不会给出RN TextInput文档中明确提到的输入值
他们还提到了解决方案,我们可以使用onEndEditing方法,以便从相同行为的文本输入中获取最新值。
请看一下公文。
我还添加了该方法的用例
前。

onEndEditing={e => {
  setNote(e.nativeEvent.text);
}}

相关问题