如何在 React 类组件中使用 redux-toolkit createSlice [英] How to use redux-toolkit createSlice with React class components
问题描述
我已经开始在功能组件中使用 redux-toolkit 切片器,(示例来自 react-redux 示例)
切片器:
export const counterSlice = createSlice({name: '计数器',初始状态:{值:0,},减速器:{增量:状态=>{状态值 += 1;},递减:状态=>{状态值 -= 1;},incrementByAmount: (state, action) =>{state.value += action.payload;},},});
在组件中使用:
const count = useSelector(selectCount);const dispatch = useDispatch();返回 (<按钮className={styles.button}aria-label =增量值";onClick={() =>调度(增量())}>)
我的问题是如何在类组件中使用这个切片器,因为我不能在它们内部使用钩子.我试过使用 connect(来自 redux),但我找不到缝合"的方法.从切片器到我的组件的操作和选择器.我也找不到任何关于此的文档.
类 vs. 函数组件和 redux-toolkit vs vanilla"redux 是两个相互独立的决策,互不影响.(不过你应该知道,对于 React 的一切,推荐函数组件和钩子而不是类组件).
<块引用>我尝试过使用 connect(来自 redux),但找不到缝合"的方法从切片器到我的组件的操作和选择器.
文档如何缝合"?使用 useDispatch
和 useSelector
时的动作和选择器?这样做,但使用 connect
高阶组件.
您发布的文档示例中的 increment()
函数不仅神奇地存在,还需要从切片中导入.您可以导出整个 actions
对象并使用 actions.increment
但您通常会看到导出为单个变量的操作.
来自文档:
<块引用>大多数情况下,您可能希望使用 ES6 解构语法将动作创建器函数提取为变量,也可能需要使用 reducer:
您的切片文件可能如下所示:
const counterSlice = createSlice(/* 与之前相同 */);//从切片中解构动作和减速器(或者您可以作为 counterSlice.actions 访问)const { 动作,reducer } = counterSlice;//导出单个动作创建器函数出口const { 增量,减量, incrementByAmount } = 动作;//通常,reducer 是默认导出,但这并不重要导出默认减速器;
connect
的第一个参数是 mapStateToProps
,您可以在其中使用选择器(内联箭头函数 state => state.something
或您导入的选择器函数)来创建来自国家的道具.这可能看起来像:
const mapStateToProps = (state) =>({计数:state.counter.value});
第二个参数 mapDispatchToProps
是可选的.如果您向动作创建者传递一个对象,您的组件将接收那些已经绑定到 dispatch
的动作创建者的版本.您可以直接调用 this.props.increment()
而不是 this.props.dispatch(increment())
.您将在带有 connect
的教程中看到这种常用的语法.
从反应"导入反应;从react-redux"导入{连接};从./counterSlice"导入{增量,减量};class MyComponent 扩展了 React.Component {使成为() {返回 (<div><h1>Count 是 {this.props.count}</h1><button onClick={() =>this.props.increment()}>增量按钮><button onClick={() =>this.props.decrement()}>递减按钮>
);}}const mapStateToProps = (状态) =>({计数:state.counter.value});const mapDispatchToProps = { 递增,递减 };导出默认连接(mapStateToProps,mapDispatchToProps)(MyComponent);
如果您完全不使用 mapDispatchToProps
参数,您的组件将接收原始 dispatch
函数.你会在你导入的动作创建者上调用调度,比如 this.props.dispatch(increment())
.此语法更类似于 useDispatch
的使用方式.connect
和 useDispatch
都允许您访问 dispatch
函数,您可以使用从动作创建器函数创建的动作调用该函数,例如increment()
或 decrement()
.
从反应"导入反应;从react-redux"导入{连接};从./counterSlice"导入{增量,减量};class MyComponent 扩展了 React.Component {使成为() {返回 (<div><h1>Count 是 {this.props.count}</h1><button onClick={() =>this.props.dispatch(increment())}>增量按钮><button onClick={() =>this.props.dispatch(decrement())}>递减按钮>
);}}const mapStateToProps = (状态) =>({计数:state.counter.value});导出默认连接(mapStateToProps)(MyComponent);
I've started using the redux-toolkit slicers in functional components, (example from react-redux example)
slicer:
export const counterSlice = createSlice({
name: 'counter',
initialState: {
value: 0,
},
reducers: {
increment: state => {
state.value += 1;
},
decrement: state => {
state.value -= 1;
},
incrementByAmount: (state, action) => {
state.value += action.payload;
},
},
});
use in component:
const count = useSelector(selectCount);
const dispatch = useDispatch();
return (
<button
className={styles.button}
aria-label="Increment value"
onClick={() => dispatch(increment())}
>
)
my question is how can I use this slicer in the class component since I cant use hooks inside them. I've tried using connect (from redux) but I can't find a way to "stitch" the actions and selectors from the slicer to my component. I couldn't find any documentation on this as well.
Class vs. function components and redux-toolkit vs "vanilla" redux are two independent decisions that don't have any impact on each other. (Though you should be aware that function components and hooks are recommended over class components for everything React).
I've tried using connect (from redux) but I can't find a way to "stitch" the actions and selectors from the slicer to my component.
How do the docs "stitch" the actions and selectors when using useDispatch
and useSelector
? Do that, but with the connect
higher-order component instead.
The increment()
function in the docs example that you posted doesn't just magically exist, it needs to be imported from the slice. You can export the entire actions
object and use actions.increment
but you usually see the actions exported as individual variables.
From the docs:
Most of the time, you'll probably want to use ES6 destructuring syntax to pull out the action creator functions as variables, and possibly the reducer as well:
Your slice file might look like this:
const counterSlice = createSlice( /* same as before */ );
// destructure actions and reducer from the slice (or you can access as counterSlice.actions)
const { actions, reducer } = counterSlice;
// export individual action creator functions
export const { increment, decrement, incrementByAmount } = actions;
// often the reducer is a default export, but that doesn't matter
export default reducer;
The first argument of connect
is mapStateToProps
, where you use selectors (either inline arrow functions state => state.something
or selector functions that you import) to create an object of props from the state. That might look like:
const mapStateToProps = (state) => ({
count: state.counter.value
});
The second argument mapDispatchToProps
is optional. If you pass an object with your action creators, your component will receive versions of those action creators that are already bound to dispatch
. You would be able to call this.props.increment()
directly rather than this.props.dispatch(increment())
. You will see this syntax commonly used in tutorials with connect
.
import React from "react";
import { connect } from "react-redux";
import { increment, decrement } from "./counterSlice";
class MyComponent extends React.Component {
render() {
return (
<div>
<h1>Count is {this.props.count}</h1>
<button onClick={() => this.props.increment()}>
Increment
</button>
<button onClick={() => this.props.decrement()}>
Decrement
</button>
</div>
);
}
}
const mapStateToProps = (state) => ({
count: state.counter.value
});
const mapDispatchToProps = { increment, decrement };
export default connect(mapStateToProps, mapDispatchToProps)(MyComponent);
If you leave off the mapDispatchToProps
argument entirely, your component receives the raw dispatch
function. You would call the dispatch on you imported action creators like this.props.dispatch(increment())
. This syntax is more similar to how useDispatch
is used. Both connect
and useDispatch
give you access to the dispatch
function and you can call that function with an action that you create from an action creator function like increment()
or decrement()
.
import React from "react";
import { connect } from "react-redux";
import { increment, decrement } from "./counterSlice";
class MyComponent extends React.Component {
render() {
return (
<div>
<h1>Count is {this.props.count}</h1>
<button onClick={() => this.props.dispatch(increment())}>
Increment
</button>
<button onClick={() => this.props.dispatch(decrement())}>
Decrement
</button>
</div>
);
}
}
const mapStateToProps = (state) => ({
count: state.counter.value
});
export default connect(mapStateToProps)(MyComponent);
这篇关于如何在 React 类组件中使用 redux-toolkit createSlice的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!