morteza
morteza

Reputation: 738

How can I use react-redux useSelector in class component?

I am new in react and trying to learn redux. I want to access the store inside a class, but it gives me an error the I cant use hook in class.

When I use this code in function (as I saw in a YouTube tutorial), it works without any problem. Here I access to counter in the store.

 function App() {
      const counter = useSelector(state => state.counter);
    
      return <div>{counter}</div>;
    }

but when I want to do this in class, it gives me an error that I can't use hooks in class.

So how can I access to my store either useSelector or useDispatch in class component?

Upvotes: 40

Views: 62292

Answers (4)

Marvin
Marvin

Reputation: 754

use HOC (Higher Order Component), for me this is the simplest way to use hooks in class component

class MyComponent extends React.PureComponent {}

const MyHoc = () => {
   const counter = useSelector();
   return <MyComponent counter={counter} />
}

or there are some cases that you want to select state that accept arguments, you may still use mapState

const mapState = ({state}) => ({
   getComments(post_id) {
      return state.comments.find(cmts => cmts.post_id === post_id)
   }
})

const connector = connect(mapState)(MyComponent)

and consume the function through this

const MyHoc = ({post_id, getComments}) => {
   const comments = getComments(post_id)
   const counter = useSelector();

   // and use the comments somewhere
   return <MyComponent counter={counter} />
}
export default connector(MyHoc)

Upvotes: 0

Medanko
Medanko

Reputation: 746

As @Ying Zuo said, your method works only with Functional Components. To solve this problem:

Instead of this line:

const counter = useSelector(state => state.counter);

You define the counter state like this:

const mapStateToProps = state => ({
    counter: state.counter
});

Then for dispatching you should use it like this:

const mapDispatchToProps = () => ({ 
    increment, 
    decrement
});

At the end you combine everything like this:

export default connect(
    mapStateToProps,
    mapDispatchToProps()
)(App);

Don't forget to import increment and decrement from your action and connect from the react-redux module.

Upvotes: 43

Amal J Varghese
Amal J Varghese

Reputation: 9

class App extends Component {
    constructor(props){
        super(props)
        this.state = {
            reduxState : {}
        }
    }
    DummyView = () => {
        const reducer = useSelector(state => state.reducer)
        useEffect(() => {
            this.setState({
                reduxState : reducer
            })
        }, [])
        return null
    }
    render(){
        return(
            <this.DummyView/>
        )
    }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Upvotes: 0

Ying Zuo
Ying Zuo

Reputation: 483

useSelector and useDispatch are React Hooks, which only work in function components.

https://reactjs.org/docs/hooks-overview.html#but-what-is-a-hook

With React Hooks, most components can and should be written with function components. If you have to write a class-based component, you can use connect from react-redux.

https://blog.logrocket.com/react-redux-connect-when-and-how-to-use-it-f2a1edab2013/

Upvotes: 20

Related Questions