Im making a react-native app and I need to get some data (articles) from a GraphQL server and then, list the articles.
My problem is, when I run my app, the first time my HomeScreen component render, the state is empty and I cant see any of the articles because the response from the server takes some time to load.
I tried to use a condition where I check if the response has no errors and has finished loading, then I save the articles to the state son when I render my articleList, the state can have the articles, but it throws an error:
Too many re-renders. React limits the number of renders to prevent an infinite loop.
All I need is to have an initial state in my application before I render my home component
My code:
const HomeScreen = () => {
const {loading, error, data} = useQuery(queryRepository.GET_ARTICLES);
const [articles, setArticles] = useState([]);
const filterByCategory = name => {
setArticles(CategoryService.filterByCategoryName(name, data.items));
};
if (loading) {
return <Spinner />;
} else if (error) {
return <Error>{error}</Error>;
} else {
setArticles(data.items);
}
return (
<View style={globalStyles.container}>
<View>
<View style={globalStyles.categoryMenuContainer}>
<CategoryMenu filterByCategory={filterByCategory} />
</View>
<View style={globalStyles.reviewsContainer}>
<ArticleList articles={articles} />
</View>
</View>
</View>
);
};
CodePudding user response:
Try useEffect for set state.
const HomeScreen = () => {
const { loading, error, data } = useQuery(queryRepository.GET_ARTICLES);
const [articles, setArticles] = useState([]);
const filterByCategory = name => {
setArticles(CategoryService.filterByCategoryName(name, data.items));
};
useEffect(() => {
if (!loading && !error && data) {
setArticles(data.items);
}
}, [data, loading, error]);
if (error) {
return <Error>{error}</Error>;
}
if (loading) {
return <Spinner />;
}
return (
<View style={globalStyles.container}>
<View>
<View style={globalStyles.categoryMenuContainer}>
<CategoryMenu filterByCategory={filterByCategory} />
</View>
<View style={globalStyles.reviewsContainer}>
<ArticleList articles={articles} />
</View>
</View>
</View>
)
};
CodePudding user response:
Everytime you call setArticles
, a new render will happen in your component, hence why you should not use setters within the render function itself, you should use hook useEffect
for that