It is rendering incorrectly when the page
state changes
I click on the category link and it checks if the link exists in category and then should set page
state to category
and likewise if I click on the recipe link it should set page
state to recipe
.
The value of isRecipe
and isCategory
are correct but it only sets the page
state correctly after refreshing the page.
It should watch the page state and if this changes then it should re-render the component
How can I re-render the component if the page state changes?
const categories = [ {name: 'first', slug: 'first'}, {name: 'second', slug: 'second'}, ] const recipes = [ {name: 'firstRecipe', slug: 'firstRecipe'}, {name: 'secondRecipe', slug: 'secondRecipe'}, ] const Categories = ({ categories, recipe, recipes }) => { const router = useRouter() const { slug } = router.query const isRecipe = !!recipes.find(recipe => recipe.slug === slug) const isCategory = !!categories.find(cat => cat.slug === slug) const [page, setPage] = useState('') useEffect(() => { !!isCategory && setPage('category') !!isRecipe && setPage('recipe') }, [page]) return ( <> <a href="/first"> category </a> <a href="/firstRecipe"> recipe </a> {page === 'category' && <Category /> } {page === 'recipe' && <Recipes /> } </> ) } export default Categories
Advertisement
Answer
The dependencies of the useEffect
hook are actually isRecipe
and isCategory
so instead of [page]
, the effect should depend on [isRecipe, isCategory]
.
Alternately, as the helpers (isCategory
and isRecipe
) are derived from the slug
, they could be moved into the hook and then only [slug]
would be required to set the proper hook dependencies.
Note: The setPage
is not required to be given to the hook dependency list as it is guaranteed to be stable by React – omitting it is safe.
Ideally, the state could be avoided entirely by a simple computation like this:
page = null if (isRecipe) { page = <Recipe /> } else if (isCategory) { page = <Category/> } ... <> ... {page} <>
There are actually three possible cases: recipe page, category page, and others that do not match the first two, which by rendering null
will most likely result in what was anticipated by the code above.
Having less state, hooks, and mutations, results in less moving parts, thus most likely less bugs 🐛