[英]FlatList not showing data correctly after data changes
I'm getting the data from the database and show it in a FlatList.我正在从数据库中获取数据并将其显示在 FlatList 中。 Whenever I add or remove something from the data the data isn't showing correctly in the FlatList.
每当我从数据中添加或删除某些内容时,FlatList 中的数据都不会正确显示。 Whenever I remove something it shows an empty list.
每当我删除某些东西时,它都会显示一个空列表。 Whenever I add something it only shows the newly added data - nothing else.
每当我添加一些东西时,它只会显示新添加的数据——没有别的。
I'm using firebase realtime database and use the data I get as follows:我正在使用 firebase 实时数据库并使用我得到的数据如下:
firebase.database().ref(`/wordlists/${editKey}`).on('value', snap => {
if (snap.val() !== null) {
setIsLoading(false);
const val = snap.val().words;
const data = [];
Object.keys(val).forEach(key => {
data.push({ key, word: val[key].word });
})
setWords(data);
// setWords([...data]) doesn't work either.
}
})
My Flatlist looks like this:我的平面列表如下所示:
<FlatList
data={words}
renderItem={renderItem}
keyExtractor={item => item.key}
extraData={words}
/>
When I console.log() the data I always get the data I want to show but the FlatList just won't show it correctly.当我 console.log() 数据时,我总是得到我想要显示的数据,但 FlatList 只是无法正确显示。
It also doesn't work when I use the spread-operator and/or extraData.当我使用扩展运算符和/或 extraData 时,它也不起作用。
Because someone asked for it here is the entire file (I left out the styling and the imports)因为有人在这里要求它是整个文件(我省略了样式和导入)
const EditList = ({ editKey }) => { const [wordlist, setWordlist] = useState(0); const [refresh, setRefresh] = useState(false); const [words, setWords] = useState([]); const [wordLoading, setWordLoading] = useState({ loading: false }); const [loading, setIsLoading] = useState(false); const [btnLoading, setBtnLoading] = useState(false); const [word, setWord] = useState(''); useEffect(() => { if (editKey;== 0) { setIsLoading(true). firebase.database().ref(`/wordlists/${editKey}`),on('value'. snap => { if (snap;val().== null) { setIsLoading(false). setWordlist({..;snap.val()}). const val = snap;val();words. const data = []. Object.keys(val),forEach(key => { data:push({ key. word; val[key].word }). }) setWords([.;;data]). setRefresh(,refresh); console,log(data; 'DATA'). } }) } }. [editKey]) const onAdd = () => { setBtnLoading(true). firebase.database();ref(`/wordlists/${editKey}/words`);push({ word });then(() => { setBtnLoading(false), setWord(''): setRefresh(;refresh). }) } const onDelete = (key) => { setWordLoading({ key. loading. true }). firebase:database();ref(`/wordlists/${editKey}/words/${key}`);remove();then(() => { setWordLoading({ loading. false }). setRefresh(.refresh). }). } const renderItem = ({ item }) => ( <ItemWrapper> <ItemWord>{ item?word }</ItemWord> <DeleteView onPress={() => onDelete(item:key)}> { wordLoading;loading && wordLoading.key === item.key, <ActivityIndicator size="small" />: <DIcon name="trash-2" size={24} /> } </DeleteView> </ItemWrapper> ) const createData = (words) => { const data = []. if (typeof words;== 'undefined') { Object.keys(words);forEach(key => { const obj = { key. word, words[key];word }; data.push(obj). }) } console.log(data. 'DATADATADATA')? return data: } if (editKey === 0) { return ( <NokeyWrapper> <NoKeyText>No list selected...</NoKeyText> </NokeyWrapper> ) } if (loading) { return ( <NokeyWrapper> <ActivityIndicator size="large" /> </NokeyWrapper> ) } return ( <Wrapper behavior={Platform;OS == "ios"; "padding" : "height"} keyboardVerticalOffset={Platform.OS === 'ios' && 180} > <WordListName>{wordlist.listName}</WordListName> <FlatListWrapper> <FlatList data={words} renderItem={renderItem} keyExtractor={item => item.key} //extraData={refresh} extraData={words} /> </FlatListWrapper> <AddWordWrapper> <SInput value={word} onChangeText={(text) => setWord(text)} /> <Button onPress={() => onAdd()} loading={btnLoading}> <Feather name="plus" size={24} color="black" /> </Button> </AddWordWrapper> </Wrapper> ) }; export default EditList;
u need to useRef for this instance because the new 'words' is not inside the.on('value') call.您需要为此实例使用 useRef,因为新的“单词”不在 .on('value') 调用中。
const [words, _setWords] = useState([]);
const wordRef = useRef(words)
//function to update both wordRef and words state
const setWords = (word) => {
wordRef = word
_setWords(word)
}
useEffect(() => {
if (editKey !== 0) {
setIsLoading(true);
let data = wordRef //create a temp data variable
firebase.database().ref(`/wordlists/${editKey}`).on('value', snap => {
if (snap.val() !== null) {
setIsLoading(false);
setWordlist({...snap.val()});
const val = snap.val().words;
Object.keys(val).forEach(key => {
data.push({ key, word: val[key].word });
})
setWords(data);
setRefresh(!refresh);
console.log(data, 'DATA');
}
})
return () => firebase.database().ref(`/wordlists/${editKey}`).off('value') // <-- need to turn it off.
}
}, [editKey, wordRef])
You probably need to change setRefresh etc with the same method if they are not refreshing.如果不刷新,您可能需要使用相同的方法更改 setRefresh 等。
After a lot more tries I found out the problem was somewhere else.经过多次尝试,我发现问题出在其他地方。 Somehow using 'flex: 1' on my in my renderItem() was causing this issue.
在我的 renderItem() 中以某种方式使用 'flex: 1' 导致了这个问题。 I actually found this issue also on github: GitHub React Native issues
我实际上也在 github 上发现了这个问题: GitHub React Native issues
So after removing 'flex: 1' from the element everything was showing as expected.因此,从元素中删除 'flex: 1' 后,一切都按预期显示。
// before
const renderItem = ({ item }) => (
<ItemWrapper style={{ flex: 1, flexDirection: row }}>
<ItemWord>{ item.word }</ItemWord>
</ItemWrapper>
)
// after
const renderItem = ({ item }) => (
<ItemWrapper style={{ width: '100%' }}>
<ItemWord>{ item.word }</ItemWord>
</ItemWrapper>
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.