当子组件 returns 有新的东西时,父组件是否重新渲染?
Is parent component re-rendered when the child component returns with something new?
据我所知,当父组件的 state
或 props
更改时,子组件正在重新渲染。
但我不知道反之亦然。
这是一个代码。
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
) 组件的状态改变了四次。
但似乎 parent(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="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
据我所知,当父组件的 state
或 props
更改时,子组件正在重新渲染。
但我不知道反之亦然。
这是一个代码。
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
) 组件的状态改变了四次。
但似乎 parent(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="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>