当函数式组件要使用 redux store 时调用这两个钩子函数。如果是类组件要使用 redux,可以使用另一个函数 connect.
函数式组件使用 Redux
例子,首先建立 redux store. 一个App 只能有唯一一个 redux store。
src/store/index.js
,此文件是一个手动建立的文件,这样命名文件是 convention.
// src/store/index.js
import { createStore } from "redux";
const counterReducer = (state = { counter: 0 }, action) => {
if (action.type === "increment") {
return { counter: state.counter + 1 };
}
if (action.type === "decrement") {
return { counter: state.counter - 1 };
}
return state;
};
const store = createStore(counterReducer);
export default store;
然后在组件树顶层用 store 来 wrap 需要使用此store的组件。
// 组件树顶层 index.js
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import "./index.css";
import App from "./App";
import store from "./store/index";
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById("root")
);
最后在需要使用 store 的组件中调用这两个钩子函数,useSelector
用来获取组件需要的state 数据。useDispatch
用来获取 dispatch 函数,
// src/components/counter.js
import { useSelector, useDispatch } from "react-redux";
import classes from "./Counter.module.css";
const Counter = () => {
const dispatch = useDispatch();
const counter = useSelector((state) => state.counter);
const incrementHandler = () => {
dispatch({ type: "increment" });
};
const decrementHandler = () => {
dispatch({ type: "decrement" });
};
const toggleCounterHandler = () => {};
return (
<main className={classes.counter}>
<h1>Redux Counter</h1>
<div className={classes.value}>{counter}</div>
<div>
<button onClick={incrementHandler}>Increment</button>
<button onClick={decrementHandler}>Decrement</button>
</div>
<button onClick={toggleCounterHandler}>Toggle Counter</button>
</main>
);
};
export default Counter;
浏览器截图,起始计数为0,点击 Increment 按钮加 1,点击Decrement 按钮减 1。
类组件使用 Redux
将上面的 src/components/counter.js
改成使用 class components:
import { Component } from "react";
import { connect } from "react-redux";
import classes from "./Counter.module.css";
class Counter extends Component {
incrementHandler() {
this.props.increment();
}
decrementHandler() {
this.props.decrement();
}
toggleCounterHandler() {}
render() {
return (
<main className={classes.counter}>
<h1>Redux Counter</h1>
<div className={classes.value}>{this.props.counter}</div>
<div>
<button onClick={this.incrementHandler.bind(this)}>Increment</button>
<button onClick={this.decrementHandler.bind(this)}>Decrement</button>
</div>
<button onClick={this.toggleCounterHandler}>Toggle Counter</button>
</main>
);
}
}
const mapStateToProps = (state) => {
return {
counter: state.counter,
};
};
const mapDispatchToProps = (dispatch) => {
return {
increment: () => dispatch({ type: "increment" }),
decrement: () => dispatch({ type: "decrement" }),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Counter);