为什么我的回调使用 redux 多次调用
Why my callback is calling multiple time with redux
我正在用 redux
编写一个 react
应用程序,避免 react-redux
,如果我们手动处理所有调度的事件,这在技术上是可行的。这是示例代码。
index.html
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.6.0/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react-dom.js"></script>
</head>
<body>
<div id="app"></div>
<script>
const appState= {
count: 0,
}
const reducer = (state, action) => {
if (typeof state === 'undefined') state = appState;
switch (action.type) {
case 'INCREMENT':
return {count: state.count+1}
case 'DECREMENT':
return {count: state.count-1}
default:
return state
}
}
var store = Redux.createStore(reducer);
const App = () => {
const [val, setVal] = React.useState(0);
handleClick = () => {
store.dispatch({type: 'INCREMENT'})
}
const unsubscribe = store.subscribe(() => {
const state = store.getState();
console.log("Listener is called")
setVal(state.count);
});
/* unsubscribe() */;
return (
<div>
<span>{val}</span>
<button onClick={handleClick}>Click</button>
</div>
);
}
ReactDOM.render(<App />, document.querySelector("#app"))
</script>
</body>
</html>
在这里,如果我第一次点击按钮,它会将日志打印到控制台一次,但是当我第二次点击按钮时,它会在日志上打印两次语句,这表明正在调用来自订阅的回调两次,为什么会这样,我该如何预防?
看起来您的组件在每个渲染周期都订阅了商店,并且由于订阅回调更新了组件状态,因此触发了另一个渲染周期。
您可能只希望组件订阅您的商店一次。
您可以使用效果订阅一次,以在更新时记录状态。使用效果清理功能退订
const App = () => {
const [val, setVal] = React.useState(0);
handleClick = () => {
store.dispatch({type: 'INCREMENT'})
}
useEffect(() => {
const unsubscribe = store.subscribe(() => {
const state = store.getState();
console.log("Listener is called", state.count);
setVal(state.count);
});
/* unsubscribe() */;
return unsubscribe; // <-- return cleanup function
}, []); // <-- empty dependency array to run once on mount
return (
<div>
<span>{val}</span>
<button onClick={handleClick}>Click</button>
</div>
);
}
我正在用 redux
编写一个 react
应用程序,避免 react-redux
,如果我们手动处理所有调度的事件,这在技术上是可行的。这是示例代码。
index.html
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/3.6.0/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.4.1/react-dom.js"></script>
</head>
<body>
<div id="app"></div>
<script>
const appState= {
count: 0,
}
const reducer = (state, action) => {
if (typeof state === 'undefined') state = appState;
switch (action.type) {
case 'INCREMENT':
return {count: state.count+1}
case 'DECREMENT':
return {count: state.count-1}
default:
return state
}
}
var store = Redux.createStore(reducer);
const App = () => {
const [val, setVal] = React.useState(0);
handleClick = () => {
store.dispatch({type: 'INCREMENT'})
}
const unsubscribe = store.subscribe(() => {
const state = store.getState();
console.log("Listener is called")
setVal(state.count);
});
/* unsubscribe() */;
return (
<div>
<span>{val}</span>
<button onClick={handleClick}>Click</button>
</div>
);
}
ReactDOM.render(<App />, document.querySelector("#app"))
</script>
</body>
</html>
在这里,如果我第一次点击按钮,它会将日志打印到控制台一次,但是当我第二次点击按钮时,它会在日志上打印两次语句,这表明正在调用来自订阅的回调两次,为什么会这样,我该如何预防?
看起来您的组件在每个渲染周期都订阅了商店,并且由于订阅回调更新了组件状态,因此触发了另一个渲染周期。
您可能只希望组件订阅您的商店一次。
您可以使用效果订阅一次,以在更新时记录状态。使用效果清理功能退订
const App = () => {
const [val, setVal] = React.useState(0);
handleClick = () => {
store.dispatch({type: 'INCREMENT'})
}
useEffect(() => {
const unsubscribe = store.subscribe(() => {
const state = store.getState();
console.log("Listener is called", state.count);
setVal(state.count);
});
/* unsubscribe() */;
return unsubscribe; // <-- return cleanup function
}, []); // <-- empty dependency array to run once on mount
return (
<div>
<span>{val}</span>
<button onClick={handleClick}>Click</button>
</div>
);
}