Javascript useCallback钩子获取旧状态值而不更新
我的回调在多次调用后返回相同的状态 我不熟悉react类中的react钩子,我本可以使用shouldcomponentupdate并解决这个问题 但是UseCallbackHook中没有参数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
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”回调(更改状态)。将其添加到依赖项列表中