只要我知道,当父组件的状态或props改变时,子组件将被重新呈现. 但我不知道反之亦然. 这是一个代码. usePromise.js(定制钩子) import { useEffect, useReducer } from 'react';const reducer = (state, action) =
但我不知道反之亦然.
这是一个代码.
usePromise.js(定制钩子)
import { useEffect, useReducer } from 'react'; const reducer = (state, action) => { switch (action.type) { case 'RESOLVED': return { ...state, resolved: action.diff }; case 'LOADING': return { ...state, loading: action.diff }; case 'ERROR': return { ...state, resolved: action.diff }; default: return state; } }; export default function usePromise(promiseCreator, deps = []) { const [state, dispatch] = useReducer(reducer, { resolved: null, loading: false, error: null }); const process = async () => { dispatch({ type: 'LOADING', diff: true }); try { const result = await promiseCreator(); dispatch({ type: 'RESOLVED', diff: result }); } catch (e) { dispatch({ type: 'ERROR', diff: e }); } dispatch({ type: 'LOADING', diff: false }); }; useEffect(() => { process(); }, deps); return state; }
usePromiseSample.js
import React from 'react'; import usePromise from './usePromise'; const wait = () => { return new Promise(resolve => setTimeout(() => resolve('Hello hooks!'), 3000) ); }; const UsePromiseSample = () => { const { resolved, loading, error } = usePromise(wait); console.log('test') if (loading) return <div>loading...</div>; if (error) return <div>error happened!</div>; if (!resolved) return null; return <div>{resolved}</div>; }; export default UsePromiseSample;
正如您在上面看到的代码,child(usePromise.js)组件的状态正在改变四次.
但似乎父级(usePromiseSample.js)也被重新渲染四次,因为测试记录了四次.
我怎样才能轻易理解这种情况?
usePromise不是子组件,而是自定义钩子.钩子本身在usePromise内部调度动作时不会被重新渲染,但是使用它的组件是.如果在另一个组件中渲染UsePromiseSample,您将看到当UsePromiseSample为父级时,父级不会重新渲染.
const { useEffect, useReducer } = React; const reducer = (state, action) => { switch (action.type) { case 'RESOLVED': return { ...state, resolved: action.diff, loading: false }; case 'ERROR': return { ...state, resolved: action.diff, loading: false }; default: return state; } }; function usePromise(promiseCreator, deps = []) { const [state, dispatch] = useReducer(reducer, { resolved: null, loading: true, error: null }); const process = () => { promiseCreator() .then(result => { dispatch({ type: 'RESOLVED', diff: result }); }) .catch(e => { dispatch({ type: 'ERROR', diff: e }); }); }; useEffect(() => { process(); }, deps); return state; } const wait = () => { return new Promise(resolve => setTimeout(() => resolve('Hello hooks!'), 3000) ); }; const UsePromiseSample = () => { const { resolved, loading, error } = usePromise(wait); console.log('UsePromiseSample rendered') if (loading) return <div>loading...</div>; if (error) return <div>error happened!</div>; if (!resolved) return null; return <div>{resolved}</div>; }; const App = () => { console.log('App rendered') return <UsePromiseSample /> } ReactDOM.render(<App />, document.getElementById("root"));
<script src="http://img.558idc.com/uploadfile/allimg/210615/20295I157-0.jpg"></script> <script src="http://img.558idc.com/uploadfile/allimg/210615/20295I5U-1.jpg"></script> <div id="root"></div>