Selector + Loadable for Search stops working on Rerender/Hot-Reload Or Suspense/Loadable flashes white.
See original GitHub issueProblem:
I’m building a small search screen, and it works great. Caching properly etc. But the problem is that If the state refreshes (via changing code and saving in IDE). Or a rerender occurs in the component: The search results are all cleared from view and the Search Bar no longer accepts input. (It just shudders on typing and the value no longer changes (is reset to ‘’)). This is the same whether I use React.Suspense
or useLoadable
+ switch statement.
Example:
import React from 'react';
import { useRecoilState, selector, atom, useRecoilValueLoadable } from 'recoil';
import axios from 'axios';
import { TextInput, FlatList, SafeAreaView, View } from 'react-native';
import SearchRow from '../search_row';
import { searchListStyles } from './search_list.style';
import DismissView from '../../common/views/dismiss_view';
import { Navigation } from '../../../core/navigation/navigator.type';
const termAtom = atom({ key: 'termAtom', default: '' });
const searchSelector = selector({
key: 'searchSelector',
get: async ({ get }) => {
const term = get(termAtom);
try {
const res = await axios({
url: `http://localhost:4000/categories/search?q=${
term || '*'
}&query_by=title`,
method: 'get',
});
return res?.data?.hits;
} catch (err) {
console.warn(err)
}
},
});
const SearchList = ({ navigation }: Navigation) => {
const [term, setTerm] = useRecoilState(termAtom);
const searchLoadable = useRecoilValueLoadable(searchSelector);
// THIS WILL CAUSE PAGE TO GO BLANK AND NOT RESPOND
useEffect(() => {
setTimeout(() => setTerm(Math.random()), 10000);
}, []);
return (
<DismissView style={searchListStyles.root}>
<SafeAreaView>
<FlatList
style={{ height: '100%' }}
showsVerticalScrollIndicator={false}
stickyHeaderIndices={[0]}
ListHeaderComponent={
<TextInput
value={term}
placeholder='Search'
onChangeText={setTerm}
style={searchListStyles.input}
/>
}
initialNumToRender={25}
data={
(Array.isArray(searchLoadable.contents) &&
searchLoadable.contents) ||
[]
}
renderItem={({ item }) => (
<React.Suspense
fallback={
<View style={{ flex: 1, backgroundColor: 'transparent' }} />
}>
<SearchRow navigation={navigation} category={item} />;
</React.Suspense>
)}
/>
</SafeAreaView>
</DismissView>
);
};
export default SearchList;
Additional
If I remove
const searchLoadable = useRecoilValueLoadable(searchSelector);
and
data={ (Array.isArray(searchLoadable.contents) && searchLoadable.contents) || []}
And replace this all with
const hits = useRecoilValue(searchSelector);
data={hits}
I then begin to see white flashing of the whole app rendering the Parent React.Suspense Loading page, while the request is fired.
So the issue is twofold:
Either I have a component that breaks on small changes or rerenders/refreshes via IDE or I have a component that completely shows/hides the global React.Suspense fallback
What is the solution?
Version 0.0.8, IOS, React Native.
Issue Analytics
- State:
- Created 3 years ago
- Comments:10
Top GitHub Comments
Seems like it would work, you’d probably want to cap the size of that array so it doesn’t eat all the memory though. And use a map so you can find results faster.
Closing as we found a resolution 😃