UseEffect the useEffect hook function is used to simulate a lifecycle function. Call this function when he first argument must be a function of the second parameter can not pass also can pass an array, when not pass any data changes of components useEffect this hook function to perform every time, and when passing the second parameter array, the array data defined in the state, Execute when the state data changes.

useEffect(() = >{})Copy the code

Let’s first define this function, which takes two arguments. Callback functions and dependent arrays.

If the callback is not a function, the error is reported directly.

function useEffect(callback, depsAry) {
    // Check whether callback is a function
    if (Object.prototype.toString.call(callback) ! = ='[object Function]') {
        throw new Error('useEffect function's first argument must be a function '); }}Copy the code

Then you need to check whether depsAry is passed. If depsAry is not passed, you can call the callback function directly.

// Check whether depsAry is delivered
if (typeof depsAry === 'undefined') {
    callback();
}
Copy the code

If depsAry is passed, we need to check if it is an array. If it is not, we will throw it wrong.

// Check whether depsAry is delivered
if (typeof depsAry === 'undefined') {
    callback();
} else {
    // Check if it is an array
    if (Object.prototype.toString.call(depsAry) ! = ='[object Array]') {
        throw new Error('The second argument to the useEffect function must be an array'); }}Copy the code

If we pass an array, we need to compare the current dependency value to the last dependency value, and execute the callback if it changes.

// Store the last dependency value
let preDepsAry = [];
// Check if it is an array
if (Object.prototype.toString.call(depsAry) ! = ='[object Array]') {
    throw new Error('The second argument to the useEffect function must be an array');
} else {
    // Compare the current dependency value with the last dependency value. Every returns true and false has changed
    const hasChanged = depsAry.every((dep, index) = > dep === preDepsAry[index]) === false;
    // If the value changes
    if (hasChanged) {
        callback();
    }
    // Synchronize dependent values
    preDepsAry = depsAry;
}

Copy the code

This is almost done, but we know that useEffect can be called multiple times, and the last value we store here is the last value, not every time. We turned the preDepsAry into a two-dimensional array, and stored the corresponding depsAry in each array.

We’re also going to use indexes here.

const preDepsAry = [];
let effectIndex = 0;
Copy the code

We can’t use preDepsAry directly when we compare, we need to make some changes.

if (Object.prototype.toString.call(depsAry) ! = ='[object Array]') {
    throw new Error('The second argument to the useEffect function must be an array');
} else {
    // Get the last status value
    const prevDeps = preDepsAry[effectIndex];
    // If it exists, do the comparison; if it does not exist, do the first execution
    // // compares the current dependency value with the last dependency value, every if it returns true has not changed, false has changed
    const hasChanged = prevDeps ? depsAry.every((dep, index) = > dep === prevDeps[index]) === false : true;
    // If the value changes
    if (hasChanged) {
        callback();
    }
    // Synchronize dependent values
    preDepsAry[effectIndex] = depsAry;
}
Copy the code

You need to increment the effectIndex multiple times

// Synchronize dependent values
preDepsAry[effectIndex] = depsAry;
effectIndex++;
Copy the code

We can’t make effectIndex increment all the time, we need to return it to 0 when the component rerenders, as in the previous render function.

function render() {
    stateIndex = 0;
    effectIndex = 0;
    ReactDOM.render(<App />.document.getElementById('root'));
}
Copy the code

So we’re done. The logic is simple.

// re-render the function
function render() {
    stateIndex = 0;
    effectIndex = 0;
    ReactDOM.render(<App />.document.getElementById('root'));
}

// Store the last dependency value
const preDepsAry = [];
let effectIndex = 0;
function useEffect(callback, depsAry) {
    // Check whether callback is a function
    if (Object.prototype.toString.call(depsAry) ! = ='[object Array]') {
        throw new Error('The second argument to the useEffect function must be an array');
    } else {
        // Get the last status value
        const prevDeps = preDepsAry[effectIndex];
        // If it exists, do the comparison; if it does not exist, do the first execution
        // // compares the current dependency value with the last dependency value, every if it returns true has not changed, false has changed
        const hasChanged = prevDeps ? depsAry.every((dep, index) = > dep === prevDeps[index]) === false : true;
        // If the value changes
        if (hasChanged) {
            callback();
        }
        // Synchronize dependent values
        preDepsAry[effectIndex] = depsAry;
        / / accumulationeffectIndex++; }}Copy the code