简体   繁体   中英

React.js run useEffect before useState set default values

I have react componet called employee.js. I use this component to create employees and update employees. I manage a state called isUpdate .

With the help of the useEffect hook I change isUpdate=true . Which means this component works as an update component. Default value for isUpdate is false.

I use formik to do the validation part.

useEffect(() => {
        if (props.location.state && props.location.state.update) {
            // update
                        
            console.log('line 1')
            
            getEmp(props.location.state.id);
            
            console.log('line 2')
        }
    }, [props.location.state, console.log('initial values', initialValues)]);

This is my useEffect hook's code. Please note the console logs "line 1" "line 2" and the "initial values" one.

My problem is initial values are printed even before the line 1 . So at that time initial values are empty. But these values are set to the formik form. Even after the initial values changes it doesn't reflect in the UI.

I came from vuejs world and new to react. In vuejs it had created life cycle hook. It runs before any thing. Here component seems loading even before the useEffect hook.

How can I fix this in react world?

useEffect is run after the DOM is created and the render has been committed to the screen. So if you are wanting to do something before the render, you'll want to look at useLayoutEffect . Most of the time, useEffect is what you need and you just need to account for asynchronous data flow.

useEffect will run every render unless you provide a dependency array. If you provide a dependency array, useEffect will only run the first time, and everytime that array of values changes (not the array itself as its memory address will change every render usually). I believe it performs a shallow comparison, so you'll want to be careful about using objects in the dependency list (mutable.js is great for this).

With those two pieces of information, you can see why your code is a bit odd.

You call useEffect with the function to run and a dependency list of [props.state.location, console.log(...)] , which means useEffect will run the first time, and anytime props.state.location changes. It looks like its an object, so whenever that object's memory address changes. The second parameter will always be undefined and therefore is not really useful in this context.

You call out that the log happens before the useEffect function runs. This makes sense since its a parameter to useEffect , and parameters have to be evaluated before the useEffect method can be invoked.

Let's revisit your question. It sounds like you are using something called Formik that is being set on initialValues however its happening after the first render, and isn't triggering a new render? I'd need to see more code related to initialValues but here's my guess. You are probably setting a value directly on initialValues instead of doing it via useState . React needs to know when to re-render a component and it does this by listening for setState calls. It does not do smart magical stuff like Mobx or VueJS, and therefore can't magically re-render itself when you change a property somewhere on state.

// Creates a state variable called isUpdate and initializes it to false.
// On re-renders, it provides isUpdate with whatever value its been updated to
const [isUpdate, setIsUpdate] = useState(false);

// Sometime in the future

// changes state and causes a component to re-render
setIsUpdate(true); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM