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.
Redux is a library that allows a React app to create a global state object that can be used in any component across the app by consuming the state object.
A function that accepts an initial state, an object of reducer functions, and a "slice name", and automatically generates action creators and action types that correspond to the reducers and state. This API is the standard approach for writing Redux logic.
You can't use Hooks inside a class component, but you can definitely mix classes and function components with Hooks in a single tree.
It also helps you organize all of your Redux-related logic for a given slice into a single file. What is createSlice? It’s a function that deals with everything you need for each slice, do you remember using createAction and createReducer manually?
Use slice the files where you want to use. In my case, I want to use Menu.tsx and Header.tsx, so I put my slice inside these two files. When you want to use these slices, you should use dispatch, in my case I used useDispatch hook in react-redux.
An object containing Redux "case reducer" functions (functions intended to handle a specific action type, equivalent to a single case statement in a switch). The keys in the object will be used to generate string action type constants, and these will show up in the Redux DevTools Extension when they are dispatched.
##Why Redux (Quickly)? Redux is a state management tool that helps you control and update your applications state more efficiently. Redux itself is a standalone library which means it’s framework agnostic. You can use it with any framework but it’s usually used with React. Why should you use it?
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);
Complete CodeSandbox
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With