Javascript useCallback钩子获取旧状态值而不更新

Javascript useCallback钩子获取旧状态值而不更新,javascript,reactjs,react-native,react-hooks,usecallback,Javascript,Reactjs,React Native,React Hooks,Usecallback,我的回调在多次调用后返回相同的状态 我不熟悉react类中的react钩子,我本可以使用shouldcomponentupdate并解决这个问题 但是UseCallbackHook中没有参数 import React, { useLayoutEffect, useState, useCallback, useEffect, } from "react"; import { StyleSheet, Text, View, Platform, YellowBox } from "re

我的回调在多次调用后返回相同的状态

我不熟悉react类中的react钩子,我本可以使用shouldcomponentupdate并解决这个问题

但是UseCallbackHook中没有参数

import React, {
  useLayoutEffect,
  useState,
  useCallback,
  useEffect,
} from "react";
import { StyleSheet, Text, View, Platform, YellowBox } from "react-native";
import { HeaderButtons, Item } from "react-navigation-header-buttons";
import HeaderButton from "../components/HeaderButton";
import { Switch } from "react-native-paper";
import Colors from "../constants/Colors";
//check use callback value first

YellowBox.ignoreWarnings([
  "Non-serializable values were found in the navigation state",
]);

const FilterSwitch = ({ label, state, onChange }) => (
  <View style={styles.filterContainer}>
    <Text>{label}</Text>
    <Switch
      value={state}
      trackColor={{ true: Colors.primaryColor }}
      thumbColor={Platform.OS === "android" ? Colors.primaryColor : ""}
      onValueChange={onChange}
    />
  </View>
);

const FiltersScreen = ({ navigation }) => {
  const [isGlutenFree, setIsGlutenFree] = useState(false);
  const [isLactoseFree, setIsLactoseFree] = useState(false);
  const [isVegan, setIsVegan] = useState(false);
  const [isVegetarian, setIsVegetarian] = useState(false);

  const saveFilters = useCallback(() => {
    console.log(isGlutenFree);
    const appliedFilters = {
      glutenFree: isGlutenFree,
      lactoseFree: isLactoseFree,
      vegan: isVegan,
      isVegetarian: isVegetarian,
    };

    console.log(appliedFilters);
  }, [isGlutenFree, isLactoseFree, isVegan, isVegetarian]);


  useLayoutEffect(() => {
    navigation.setOptions({
      headerTitle: "Filter Meals",
      headerLeft: () => (
        <HeaderButtons HeaderButtonComponent={HeaderButton}>
          <Item
            title="Menu"
            iconName="ios-menu"
            onPress={() => {
              navigation.toggleDrawer();
            }}
          />
        </HeaderButtons>
      ),
      headerRight: () => (
        <HeaderButtons HeaderButtonComponent={HeaderButton}>
          <Item
            title="Save"
            iconName="ios-save"
            onPress={() => saveFilters()}
          />
        </HeaderButtons>
      ),
    });
  }, [navigation]);
  return (
    <View style={styles.screen}>
      <Text style={styles.title}>Available Filters / Restrictions</Text>
      <FilterSwitch
        label="Gluten Free"
        state={isGlutenFree}
        onChange={(newValue) => {
          setIsGlutenFree(newValue);
        }}
      />
      <FilterSwitch
        label="Lactos Free"
        state={isLactoseFree}
        onChange={(newValue) => setIsLactoseFree(newValue)}
      />
      <FilterSwitch
        label="Vegan Free"
        state={isVegan}
        onChange={(newValue) => setIsVegan(newValue)}
      />
      <FilterSwitch
        label="Vegetarian Free"
        state={isVegetarian}
        onChange={(newValue) => setIsVegetarian(newValue)}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  screen: {
    flex: 1,
    alignItems: "center",
  },
  filterContainer: {
    flexDirection: "row",
    justifyContent: "space-between",
    alignItems: "center",
    width: "80%",
    marginVertical: 15,
  },
  title: {
    fontFamily: "open-sans-bold",
    fontSize: 22,
    margin: 20,
    textAlign: "center",
  },
});
export default FiltersScreen;
import-React{
使用布局效果,
useState,
使用回调,
使用效果,
}从“反应”;
从“react native”导入{样式表、文本、视图、平台、黄盒};
从“反应导航标题按钮”导入{HeaderButtons,Item};
从“./components/HeaderButton”导入HeaderButton;
从“react native paper”导入{Switch};
从“./常量/颜色”导入颜色;
//选中“首先使用回调值”
YellowBox.ignoreWarnings([
“在导航状态下找到了不可序列化的值”,
]);
常量筛选器开关=({label,state,onChange})=>(
{label}
);
常量过滤器屏幕=({navigation})=>{
const[isglumnfree,setisglumnfree]=useState(false);
const[isLactoseFree,setIsLactoseFree]=useState(false);
const[isVegan,setIsVegan]=useState(false);
const[is素食主义者,setis素食主义者]=useState(false);
const saveFilters=useCallback(()=>{
console.log(isrumnfree);
常量appliedFilters={
无麸质:无麸质,
不含乳糖:不含乳糖,
素食主义者:我是素食主义者,
是素食者吗,
};
控制台日志(appliedFilters);
},[无麸质,无麸质,纯素,纯素];
useLayoutEffect(()=>{
navigation.setOptions({
标题:“过滤膳食”,
标题左侧:()=>(
{
navigation.toggleDrawer();
}}
/>
),
头灯:()=>(
saveFilters()}
/>
),
});
},[导航];
返回(
可用过滤器/限制
{
SetIsGrumnFree(新值);
}}
/>
SetIsActoseFree(newValue)}
/>
setIsVegan(新值)}
/>
Setis素食者(新值)}
/>
);
};
const styles=StyleSheet.create({
屏幕:{
弹性:1,
对齐项目:“中心”,
},
过滤器容器:{
flexDirection:“行”,
辩护内容:“间隔空间”,
对齐项目:“中心”,
宽度:“80%”,
澳门时间:15,,
},
标题:{
fontFamily:“开放式无边框”,
尺寸:22,
差额:20,
textAlign:“居中”,
},
});
导出默认过滤器屏幕;
我怎样才能解决这个问题?
我已经阅读了官方文档,但在那里找不到任何相关问题

您的代码的问题是,即使您为所有依赖数组提供了
useCallback
,您也只使用了
onPress={()=>saveFilters()中函数的
第一个闭包值
由于此代码是在
内部执行的,因此使用LayoutEffect
仅在
导航上运行

useLayoutEffect(() => {
    navigation.setOptions({
      headerTitle: "Filter Meals",
      headerLeft: () => (
        <HeaderButtons HeaderButtonComponent={HeaderButton}>
          <Item
            title="Menu"
            iconName="ios-menu"
            onPress={() => {
              navigation.toggleDrawer();
            }}
          />
        </HeaderButtons>
      ),
      headerRight: () => (
        <HeaderButtons HeaderButtonComponent={HeaderButton}>
          <Item
            title="Save"
            iconName="ios-save"
            onPress={() => saveFilters()}
          />
        </HeaderButtons>
      ),
    });
  }, [navigation, saveFilters]);
这里的解决方案是
在导航更改和
saveFilters
更改上更新导航选项

useLayoutEffect(() => {
    navigation.setOptions({
      headerTitle: "Filter Meals",
      headerLeft: () => (
        <HeaderButtons HeaderButtonComponent={HeaderButton}>
          <Item
            title="Menu"
            iconName="ios-menu"
            onPress={() => {
              navigation.toggleDrawer();
            }}
          />
        </HeaderButtons>
      ),
      headerRight: () => (
        <HeaderButtons HeaderButtonComponent={HeaderButton}>
          <Item
            title="Save"
            iconName="ios-save"
            onPress={() => saveFilters()}
          />
        </HeaderButtons>
      ),
    });
  }, [navigation, saveFilters]);
useLayoutEffect(()=>{
navigation.setOptions({
标题:“过滤膳食”,
标题左侧:()=>(
{
navigation.toggleDrawer();
}}
/>
),
头灯:()=>(
saveFilters()}
/>
),
});
},[navigation,saveFilters]);
p.S.在这种情况下,我觉得钩子的实现有时会变得粗糙或效率低下。也调试
闭包
比调试
上下文
困难得多 类组件)


useCallback
只需记忆回调(确保其引用保持不变,除非它的一个依赖项已更改。看起来与您编写的回调不一样(只需创建一个对象并记录它)。如果您调用
setisplanet
它会改变。例如,我正在调用过滤器上的每个setState调用switch自定义组件,并且我已经提供了每个值,即使我的状态在每个渲染上都在改变。您的
useNavigationEffect
钩子没有将
saveFilters
回调作为依赖项,因此它永远不会调用“new”回调(更改状态)。将其添加到依赖项列表中