我得到了3页
homepage
、productList
和productDetails
从homepage
到productList
时,我通过一个路由参数
navigation.navigate('productList', { showCategory: 'productListA'} )
InitialProcess when component mounted
安装组件时,在productList页面内。我这样声明使用状态。
const {showCateory} = route.params;
const [activeTab, setActiveTab] = useState(showCateory);
并使用activeTab 调用api
useEffect(() => {
const unsubscribe = navigation.addListener('focus', () => {
async function fetchData() {
try {
await dispatch(
fetchProductList(
activeTab,
),
);
} catch (err) {
console.log(err);
}
}
fetchData();
});
return unsubscribe;
}, []);
User Interaction
但我也在productList中添加了按钮,这样用户就可以更改当前活动选项卡
<TouchableOpacity onPress={() => changeTab()}></TouchableOpacity>
const changeTab = async () => {
await setActiveTab('productListB'),
await dispatch(fetchProductList(activeTab)
}
请注意,现在active tab
和data coming from api is different
是从组件开始安装时开始的。
Navigation Change again
当使用从productList
转到productDetails
时。一切都很好。
但在产品细节中,我将带着这个回到productList。navigation.goBack()
。
当我回到productList页面时,activeTab会变回productListA
,数据会变回当component is mounted
时
调用navigation.goBack()
时,我可以通过或更改路由参数吗?
在useEffect depedieces中添加activeTab
。
正如医生所说的
依赖项数组不会作为参数传递给effect函数。不过,从概念上讲,这就是它们所代表的:effect函数中引用的每个值也应该出现在dependencies数组中。将来,一个足够高级的编译器可以自动创建这个数组。
useEffect(() => {
const unsubscribe = navigation.addListener('focus', () => {
async function fetchData() {
try {
await dispatch(
fetchProductList(
//this value will always updated when activeTab change
activeTab,
),
);
} catch (err) {
console.log(err);
}
}
fetchData();
});
return unsubscribe;
}, [activeTab]); //<<<<< here
您还需要知道setState((并不总是立即更新组件。请参阅此处
因此更改此
const changeTab = async () => {
//await setActiveTab('productListB'),
//await dispatch(fetchProductList(activeTab)
setActiveTab('productListB')
dispatch(fetchProductList('productListB'))
}
这可能是因为当您返回屏幕时,route.params
仍设置为{ showCategory: 'productListA'}
。
如果是这种情况,您可以通过像一样更改changeTab()
中的params
对象来修复它
navigation.setParams({
showCategory: 'productListB',
});
我希望这能解决你的问题。
之所以会发生这种情况,是因为焦点侦听器内部的回调函数在定义函数时(在初始页面呈现时(使用状态的初始值。在侦听器的整个生命周期中,回调函数都使用这个过时的状态值。你可以在这个答案中阅读更多关于这种行为的信息
尽管Ahmed Gaber的答案在这种情况下有效,因为侦听器在每次状态更改后都会被清除和重新定义。另一个常见的解决方法是使用useRef而不是useEffect。ref基本上是一个配方,它提供了一个可以通过引用传递的可变对象。
在您的情况下,您可以使用useRef钩子将导航参数值的activeTab初始化为:
const activeTab = useRef(showCateory);
并且焦点侦听器回调函数应该更改为使用引用当前值作为
useEffect(() => {
const unsubscribe = navigation.addListener('focus', () => {
async function fetchData() {
try {
await dispatch(
fetchProductList(
activeTab.current, //<<<<<<---------here
),
);
} catch (err) {
console.log(err);
}
}
fetchData();
});
return unsubscribe;
}, []);
changeTab功能可以直接更新参考电流值
const changeTab = async () => {
setActiveTab.current = 'productListB';
dispatch(fetchProductList('productListB'))
}