React native:useState 没有正确更新
React native: useState not updating correctly
我是 React Native 的新手,目前正在为无限滚动列表视图而苦苦挣扎。这是一个日历列表,需要根据所选公司(作为道具给出)进行更改。问题是:道具(以及 myCompany
状态已更改,但在 _loadMoreAsync
方法中 prop.company
和 myCompany
都保持其初始值。
import * as React from 'react';
import { FlatList } from 'react-native';
import * as Api from '../api/api';
import InfiniteScrollView from 'react-native-infinite-scroll-view';
function CalenderFlatList(props: { company: any }) {
const [myCompany, setMyCompany] = React.useState(null);
const [data, setData] = React.useState([]);
const [canLoadMore, setCanLoadMore] = React.useState(true);
const [startDate, setStartDate] = React.useState(undefined);
let loading = false;
React.useEffect(() => {
setMyCompany(props.company);
}, [props.company]);
React.useEffect(() => {
console.log('set myCompany to ' + (myCompany ? myCompany.name : 'undefined'));
_loadMoreAsync();
}, [myCompany]);
async function _loadMoreAsync() {
if ( loading )
return;
loading = true;
if ( myCompany == null ) {
console.log('no company selected!');
return;
} else {
console.log('use company: ' + myCompany.name);
}
Api.fetchCalendar(myCompany, startDate).then((result: any) => {
// code is a little more complex here to keep the already fetched entries in the list...
setData(result);
// to above code also calculates the last day +1 for the next call
setStartDate(lastDayPlusOne);
loading = false;
});
}
const renderItem = ({ item }) => {
// code to render the item
}
return (
<FlatList
data={data}
renderScrollComponent={props => <InfiniteScrollView {...props} />}
renderItem={renderItem}
keyExtractor={(item: any) => '' + item.uid }
canLoadMore={canLoadMore}
onLoadMoreAsync={() => _loadMoreAsync() }
/>
);
}
我不明白的是为什么 myCompany
在 _loadMoreAsync
中根本没有更新,而 startDate
正确更新并准确加载日历的下一个条目。
道具 company
更改后,我希望得到以下输出:
set myCompany to companyName
use company companyName
但我得到的是:
set myCompany to companyName
no company selected!
我试着减少了一些代码以将其剥离到最重要的部分。对此有何建议?
Google 用于 useEffect 陈旧关闭。
当从 useEffect 调用该函数时,它是从陈旧的上下文中调用的 - 这显然是一个 javascript 功能 :) 所以基本上您遇到的行为是预期的,您需要找到一种方法来解决它。
一种方法可能是向从 useEffect 传递的 _loadMoreAsync 添加一个(可选)参数。如果此参数未定义(从其他地方调用时它将是),则使用来自状态的值。
尝试
<FlatList
data={data}
renderScrollComponent={props => <InfiniteScrollView {...props} />}
renderItem={renderItem}
keyExtractor={(item: any) => '' + item.uid }
canLoadMore={canLoadMore}
onLoadMoreAsync={() => _loadMoreAsync() }
extraData={myCompany}
/>
如果您的 FlatList 依赖于状态变量,则需要将该变量传递给 extraData 属性以触发列表的重新呈现。更多信息 here
这个问题睡了两个晚上我自己解决了。原因是另一段使用 React.useCallback() 的代码的影响。并且由于“useCallback 将 return 一个记忆版本的回调,只有当其中一个依赖项发生变化时才会发生变化”(https://reactjs.org/docs/hooks-reference.html#usecallback)代码使用变量的旧(或初始)状态。
从头开始新建整个页面后,我发现这就是该行为的原因。
我是 React Native 的新手,目前正在为无限滚动列表视图而苦苦挣扎。这是一个日历列表,需要根据所选公司(作为道具给出)进行更改。问题是:道具(以及 myCompany
状态已更改,但在 _loadMoreAsync
方法中 prop.company
和 myCompany
都保持其初始值。
import * as React from 'react';
import { FlatList } from 'react-native';
import * as Api from '../api/api';
import InfiniteScrollView from 'react-native-infinite-scroll-view';
function CalenderFlatList(props: { company: any }) {
const [myCompany, setMyCompany] = React.useState(null);
const [data, setData] = React.useState([]);
const [canLoadMore, setCanLoadMore] = React.useState(true);
const [startDate, setStartDate] = React.useState(undefined);
let loading = false;
React.useEffect(() => {
setMyCompany(props.company);
}, [props.company]);
React.useEffect(() => {
console.log('set myCompany to ' + (myCompany ? myCompany.name : 'undefined'));
_loadMoreAsync();
}, [myCompany]);
async function _loadMoreAsync() {
if ( loading )
return;
loading = true;
if ( myCompany == null ) {
console.log('no company selected!');
return;
} else {
console.log('use company: ' + myCompany.name);
}
Api.fetchCalendar(myCompany, startDate).then((result: any) => {
// code is a little more complex here to keep the already fetched entries in the list...
setData(result);
// to above code also calculates the last day +1 for the next call
setStartDate(lastDayPlusOne);
loading = false;
});
}
const renderItem = ({ item }) => {
// code to render the item
}
return (
<FlatList
data={data}
renderScrollComponent={props => <InfiniteScrollView {...props} />}
renderItem={renderItem}
keyExtractor={(item: any) => '' + item.uid }
canLoadMore={canLoadMore}
onLoadMoreAsync={() => _loadMoreAsync() }
/>
);
}
我不明白的是为什么 myCompany
在 _loadMoreAsync
中根本没有更新,而 startDate
正确更新并准确加载日历的下一个条目。
道具 company
更改后,我希望得到以下输出:
set myCompany to companyName
use company companyName
但我得到的是:
set myCompany to companyName
no company selected!
我试着减少了一些代码以将其剥离到最重要的部分。对此有何建议?
Google 用于 useEffect 陈旧关闭。
当从 useEffect 调用该函数时,它是从陈旧的上下文中调用的 - 这显然是一个 javascript 功能 :) 所以基本上您遇到的行为是预期的,您需要找到一种方法来解决它。
一种方法可能是向从 useEffect 传递的 _loadMoreAsync 添加一个(可选)参数。如果此参数未定义(从其他地方调用时它将是),则使用来自状态的值。
尝试
<FlatList
data={data}
renderScrollComponent={props => <InfiniteScrollView {...props} />}
renderItem={renderItem}
keyExtractor={(item: any) => '' + item.uid }
canLoadMore={canLoadMore}
onLoadMoreAsync={() => _loadMoreAsync() }
extraData={myCompany}
/>
如果您的 FlatList 依赖于状态变量,则需要将该变量传递给 extraData 属性以触发列表的重新呈现。更多信息 here
这个问题睡了两个晚上我自己解决了。原因是另一段使用 React.useCallback() 的代码的影响。并且由于“useCallback 将 return 一个记忆版本的回调,只有当其中一个依赖项发生变化时才会发生变化”(https://reactjs.org/docs/hooks-reference.html#usecallback)代码使用变量的旧(或初始)状态。
从头开始新建整个页面后,我发现这就是该行为的原因。