React hooks使用场景浅析

Effect 不依赖任何值

const Counter = () => {
    const [count, setCount] = useState(0);

    useEffect(() => {
        const id = setInterval(() => {
            setCount(count + 1)
        }, 1000)
        return () => clearInterval(id);
    }, [])

    return (
        <div>
            {count}
        </div>
    )
}

Effect依赖某个值

const Counter = () => {
    const [count, setCount] = useState(0);

    useEffect(() => {
        const id = setInterval(() => {
            setCount(count + 1)
        }, 1000)
        return () => clearInterval(id);
    }, [count])

    return (
        <div>
            {count}
        </div>
    )
}

Effect自给自足

使用类似 setState的函数形式

const Counter = () => {
    const [count, setCount] = useState(0);

    useEffect(() => {
        const id = setInterval(() => {
            setCount(count => count +1)
        }, 1000)
        return () => clearInterval(id);
    }, [step])

    return (
        <div>
            {count}
        </div>
    )
}

相互依赖的状态

setCount(c => c + 1)并不完美,假设我们有两个相互依赖的状态,我们想基于某个props计算下一次的state,并不能做到。

const Counter = () => {
    const [count, setCount] = useState(0);
    const [step, setStep] = useState(1);

    useEffect(() => {
        const id = setInterval(() => {
            setCount(count => count + step)
        }, 1000)
        return () => clearInterval(id);
    }, [step])

    return (
        <div>
            {count}
            <input value={step} onChange={e => setStep(Number(e.target.value))} />
        </div>
    )
}

使用useReducer

const initialState = {
    count: 0,
    step: 1,
};
  
function reducer(state, action) {
    const { count, step } = state;
    if (action.type === 'tick') {
        return { count: count + step, step };
    } else if (action.type === 'step') {
        return { count, step: action.step };
    } else {
        throw new Error();
    }
}

const Counter = () => {
    const [state, dispatch] = useReducer(reducer, initialState);
    const { count, step } = state;

    useEffect(() => {
        const id = setInterval(() => {
            dispatch({type:'tick'});
        }, 1000)
        return () => clearInterval(id);
    }, [dispatch])

    return (
        <div>
            {count}
            <input value={step} onChange={e => {
                dispatch({
                    type: 'step',
                    step: Number(e.target.value)
                });
            }} />
        </div>
    )
}

当然你也可以把依赖的dispatch去掉,useReducer是hooks中的作弊模式,它可以把相互依赖的逻辑分开,避免不必要的effect调用。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容