为什么 useCallback return 是一个空数组
why does useCallback return an empty array
在 React 原生应用中,
我正在尝试从异步函数获取数据,这将使我返回 Promise
Q1。因此,在 getAlarms.then() 函数中,过滤了未定义的大小写,并在我的控制台中打印了一个 空数组。
并且在 vscode 中保存代码后,控制台打印一个包含正确数据的数组
Q2.the 我之所以分别使用 useLayoutEffect 和 useEffect 的原因是
我只想将数据获取代码与反应导航 header setOption 代码分开
但我不确定这是否是一个好习惯
有没有更好的方法来做到这一点?
编辑:我正在使用 react-native-simple-alarm
const [alarms, setAlarms] = useState<AlarmType[]>([]);
const fetchData = useCallback(() => {
getAlarms().then(response => {
if (response) setAlarms(response);
else console.log('undefined | empty array returned');
});
}, []);
useLayoutEffect(() => {
fetchData();
const willFocusSubscription = navigation.addListener('focus', () => {
fetchData();
});
console.log(alarms) // here, this function is called twice, and return empty array
return willFocusSubscription;
}, []);
useEffect(() => {
navigation.setOptions({
headerLeft: () => <Icon name="trash-can-outline" size={30}
onPress={() => {
deleteAllAlarms();
fetchData();
}}/>,
headerTitle: 'Alarm',
headerRight: () =><Icon name="plus" size={30} onPress={() => navigation.navigate('ModalStackView')}/>,
});
}, []);
在getAlarms.ts
export const getAlarms = async () => {
try {
return await RNGetAlarms();
} catch (error) {
console.log('setting call error' + error);
}
};
useLayoutEffect 在 React 的渲染周期之前被调用,这意味着在渲染代码中的 JSX 内容之前调用这个钩子。
因此,如果在 JSX 渲染之前有任何要求,例如更改 header 名称、显示 header 左右按钮等
和在初始渲染周期完成后调用 useEffect。当 JSX 代码完成渲染 UI 部分时。
所以,我认为您的代码应该如下所示:
const [alarms, setAlarms] = useState<AlarmType[]>([]);
const fetchData = useCallback(() => {
getAlarms().then(response => {
if (response) setAlarms(response);
else console.log('undefined | empty array returned');
});
}, []);
useEffect(() => {
const willFocusSubscription = navigation.addListener('focus', () => {
fetchData();
});
return willFocusSubscription;
}, [fetchData, navigation]);
useLayoutEffect(() => {
navigation.setOptions({
headerLeft: () => <Icon name="trash-can-outline" size={30}
onPress={() => {
deleteAllAlarms();
fetchData();
}}/>,
headerTitle: 'Alarm',
headerRight: () =><Icon name="plus" size={30} onPress={() => navigation.navigate('ModalStackView')}/>,
});
}, [deleteAllAlarms, fetchData, navigation]);
在 React 原生应用中,
我正在尝试从异步函数获取数据,这将使我返回 Promise
Q1。因此,在 getAlarms.then() 函数中,过滤了未定义的大小写,并在我的控制台中打印了一个 空数组。
并且在 vscode 中保存代码后,控制台打印一个包含正确数据的数组
Q2.the 我之所以分别使用 useLayoutEffect 和 useEffect 的原因是 我只想将数据获取代码与反应导航 header setOption 代码分开 但我不确定这是否是一个好习惯
有没有更好的方法来做到这一点? 编辑:我正在使用 react-native-simple-alarm
const [alarms, setAlarms] = useState<AlarmType[]>([]);
const fetchData = useCallback(() => {
getAlarms().then(response => {
if (response) setAlarms(response);
else console.log('undefined | empty array returned');
});
}, []);
useLayoutEffect(() => {
fetchData();
const willFocusSubscription = navigation.addListener('focus', () => {
fetchData();
});
console.log(alarms) // here, this function is called twice, and return empty array
return willFocusSubscription;
}, []);
useEffect(() => {
navigation.setOptions({
headerLeft: () => <Icon name="trash-can-outline" size={30}
onPress={() => {
deleteAllAlarms();
fetchData();
}}/>,
headerTitle: 'Alarm',
headerRight: () =><Icon name="plus" size={30} onPress={() => navigation.navigate('ModalStackView')}/>,
});
}, []);
在getAlarms.ts
export const getAlarms = async () => {
try {
return await RNGetAlarms();
} catch (error) {
console.log('setting call error' + error);
}
};
useLayoutEffect 在 React 的渲染周期之前被调用,这意味着在渲染代码中的 JSX 内容之前调用这个钩子。
因此,如果在 JSX 渲染之前有任何要求,例如更改 header 名称、显示 header 左右按钮等
和在初始渲染周期完成后调用 useEffect。当 JSX 代码完成渲染 UI 部分时。
所以,我认为您的代码应该如下所示:
const [alarms, setAlarms] = useState<AlarmType[]>([]);
const fetchData = useCallback(() => {
getAlarms().then(response => {
if (response) setAlarms(response);
else console.log('undefined | empty array returned');
});
}, []);
useEffect(() => {
const willFocusSubscription = navigation.addListener('focus', () => {
fetchData();
});
return willFocusSubscription;
}, [fetchData, navigation]);
useLayoutEffect(() => {
navigation.setOptions({
headerLeft: () => <Icon name="trash-can-outline" size={30}
onPress={() => {
deleteAllAlarms();
fetchData();
}}/>,
headerTitle: 'Alarm',
headerRight: () =><Icon name="plus" size={30} onPress={() => navigation.navigate('ModalStackView')}/>,
});
}, [deleteAllAlarms, fetchData, navigation]);