如何在每次渲染时从 运行 中避免 useReducer(reducer, getInitialState()) 中使用的 getInitialState() 函数?
How to avoid getInitialState() function used in useReducer( reducer, getInitialState() ) from running on every render?
请参阅下面的代码段。
通过这样做:
React.useState(()=>getInitialState2());
您避免运行在每个渲染的useState
中使用getInitialState2()
。
但这似乎对 useReducer
挂钩不起作用。
问题
有没有办法避免 运行 在每个渲染的 useReducer
挂钩上的 initialState
参数中使用的函数?
function App() {
const [state,dispatch] = React.useReducer(reducer,getInitialState());
const [state2,setState2] = React.useState(()=>getInitialState2());
return(
<React.Fragment>
<div>
State: {state}
</div>
<div>
State2: {state2}
</div>
<div>
<button onClick={() => dispatch({type: "INCREMENT"})}>+</button>
<button onClick={() => dispatch({type: "DECREMENT"})}>-</button>
</div>
</React.Fragment>
);
}
function getInitialState() {
console.log("From getInitialState...");
return 0;
}
function getInitialState2() {
console.log("From getInitialState2...");
return 0;
}
function reducer(state,action) {
switch(action.type) {
case "INCREMENT": {
return state + 1;
}
case "DECREMENT": {
return state - 1;
}
default: {
return state;
}
}
}
ReactDOM.render(<App/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>
通过调用它,您可以在每次渲染时 运行 它。要使 initialisation lazy,传递一个函数。另外,lazy init 是 useReducer
的第 3 个参数。无论您作为 useReducer
的第二个参数提供什么,都将传递给惰性初始化函数,但您可以忽略它。
const [state,dispatch] = React.useReducer(reducer, null, getInitialState);
或者用箭头函数包裹它,如果你需要用 props 的值初始化它:
const [state,dispatch] = React.useReducer(reducer, null, () => getInitialState(props.something));
演示:
function App() {
const [state,dispatch] = React.useReducer(reducer,null,getInitialState);
const [state2,setState2] = React.useState(()=>getInitialState2());
return(
<React.Fragment>
<div>
State: {state}
</div>
<div>
State2: {state2}
</div>
<div>
<button onClick={() => dispatch({type: "INCREMENT"})}>+</button>
<button onClick={() => dispatch({type: "DECREMENT"})}>-</button>
</div>
</React.Fragment>
);
}
function getInitialState() {
console.log("From getInitialState...");
return 0;
}
function getInitialState2() {
console.log("From getInitialState2...");
return 0;
}
function reducer(state,action) {
switch(action.type) {
case "INCREMENT": {
return state + 1;
}
case "DECREMENT": {
return state - 1;
}
default: {
return state;
}
}
}
ReactDOM.render(<App/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>
由于每次渲染发生时组件都会重新运行,一种选择是仅在组件外部 检索一次初始状态:
const initialState1 = getInitialState();
function App() {
const [state,dispatch] = React.useReducer(reducer, initialState1);
const [state2,setState2] = React.useState(()=>getInitialState2());
return(
<React.Fragment>
<div>
State: {state}
</div>
<div>
State2: {state2}
</div>
<div>
<button onClick={() => dispatch({type: "INCREMENT"})}>+</button>
<button onClick={() => dispatch({type: "DECREMENT"})}>-</button>
</div>
</React.Fragment>
);
}
function getInitialState() {
console.log("From getInitialState...");
return 0;
}
function getInitialState2() {
console.log("From getInitialState2...");
return 0;
}
function reducer(state,action) {
switch(action.type) {
case "INCREMENT": {
return state + 1;
}
case "DECREMENT": {
return state - 1;
}
default: {
return state;
}
}
}
ReactDOM.render(<App/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root" />
请参阅下面的代码段。
通过这样做:
React.useState(()=>getInitialState2());
您避免运行在每个渲染的useState
中使用getInitialState2()
。
但这似乎对 useReducer
挂钩不起作用。
问题
有没有办法避免 运行 在每个渲染的 useReducer
挂钩上的 initialState
参数中使用的函数?
function App() {
const [state,dispatch] = React.useReducer(reducer,getInitialState());
const [state2,setState2] = React.useState(()=>getInitialState2());
return(
<React.Fragment>
<div>
State: {state}
</div>
<div>
State2: {state2}
</div>
<div>
<button onClick={() => dispatch({type: "INCREMENT"})}>+</button>
<button onClick={() => dispatch({type: "DECREMENT"})}>-</button>
</div>
</React.Fragment>
);
}
function getInitialState() {
console.log("From getInitialState...");
return 0;
}
function getInitialState2() {
console.log("From getInitialState2...");
return 0;
}
function reducer(state,action) {
switch(action.type) {
case "INCREMENT": {
return state + 1;
}
case "DECREMENT": {
return state - 1;
}
default: {
return state;
}
}
}
ReactDOM.render(<App/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>
通过调用它,您可以在每次渲染时 运行 它。要使 initialisation lazy,传递一个函数。另外,lazy init 是 useReducer
的第 3 个参数。无论您作为 useReducer
的第二个参数提供什么,都将传递给惰性初始化函数,但您可以忽略它。
const [state,dispatch] = React.useReducer(reducer, null, getInitialState);
或者用箭头函数包裹它,如果你需要用 props 的值初始化它:
const [state,dispatch] = React.useReducer(reducer, null, () => getInitialState(props.something));
演示:
function App() {
const [state,dispatch] = React.useReducer(reducer,null,getInitialState);
const [state2,setState2] = React.useState(()=>getInitialState2());
return(
<React.Fragment>
<div>
State: {state}
</div>
<div>
State2: {state2}
</div>
<div>
<button onClick={() => dispatch({type: "INCREMENT"})}>+</button>
<button onClick={() => dispatch({type: "DECREMENT"})}>-</button>
</div>
</React.Fragment>
);
}
function getInitialState() {
console.log("From getInitialState...");
return 0;
}
function getInitialState2() {
console.log("From getInitialState2...");
return 0;
}
function reducer(state,action) {
switch(action.type) {
case "INCREMENT": {
return state + 1;
}
case "DECREMENT": {
return state - 1;
}
default: {
return state;
}
}
}
ReactDOM.render(<App/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>
由于每次渲染发生时组件都会重新运行,一种选择是仅在组件外部 检索一次初始状态:
const initialState1 = getInitialState();
function App() {
const [state,dispatch] = React.useReducer(reducer, initialState1);
const [state2,setState2] = React.useState(()=>getInitialState2());
return(
<React.Fragment>
<div>
State: {state}
</div>
<div>
State2: {state2}
</div>
<div>
<button onClick={() => dispatch({type: "INCREMENT"})}>+</button>
<button onClick={() => dispatch({type: "DECREMENT"})}>-</button>
</div>
</React.Fragment>
);
}
function getInitialState() {
console.log("From getInitialState...");
return 0;
}
function getInitialState2() {
console.log("From getInitialState2...");
return 0;
}
function reducer(state,action) {
switch(action.type) {
case "INCREMENT": {
return state + 1;
}
case "DECREMENT": {
return state - 1;
}
default: {
return state;
}
}
}
ReactDOM.render(<App/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root" />