Home > Blockchain >  What is the correct way to set state from another hook?
What is the correct way to set state from another hook?

Time:12-29

I have a query parameter like this:

const router = useRouter()
const { name } = router.query

I want to use this name and pass it to a value that has state:

const [queryName, setQueryName] = useState('')

The issue is I cannot pass it as the default, like this: useState(name) because the name updates.

So rather than using the name as the default value I'd have to set it.

setQueryName(name)

This however is also not valid, I can't just set it within the component like this.

So I'd have to use useEffect

useEffect(() => {
    setQueryName(name)
}, [name])

However this is triggering a infinite error:

Maximum update depth exceeded. This can happen when a component calls setState inside useEffect, but useEffect either doesn't have a dependency array, or one of the dependencies changes on every render.

What is the correct way to set state from another hook?

CodePudding user response:

Turns out I was pulling the prop from the router and doing some manipulation, I wrapped this logic in a memo and it works.

const useName = (): ComponentBlock | null => {
    const router = useRouter()
    return useMemo(() => {
        const { name } = router.query
        if (name && typeof name === 'string') {
            return name
        }
        return null;
    }, [router])
}

and

    const queryName = useName()
    const [name, setName] = useState('')

    useEffect(() => {
        setName(name)
    }, [name])

CodePudding user response:

You can use useLocation() hook in react router v5

const search = useLocation().search;
const name = new URLSearchParams(search).get('name');
  
const [value, setValue] = useState(name);

CodePudding user response:

There is a little trick you could do.

And I imagine it would make the code more readable. The value you receive from url is used as initial value and it can be changed later by some UI in the page, right?

const router = useRouter();
const { name: initialName } = router.query; // get name, but we'll be calling it "initialName" onward.

const [name, setName] = useState(initialName);
  • Related