Reputation: 191
I am trying to exchange some data between components in my React App and trying to use Redux for the purpose.
I am really looking for simple functionality (storing accesstoken, retrieving accesstoken).
I have one file in folder src/reducers/currenttokenreducer.js:
const currentTokenReducer = (state, action) => {
switch(action.type){
case 'SETTOKEN':
return action.payload
case 'GETTOKEN':
return state
default: return null
}
}
export default currentTokenReducer;
then I have an index.js in src/reducers/:
import currentUserReducer from './currentuser.js'
import currentTokenReducer from'./currenttoken.js'
import {combineReducers} from 'redux'
const allReducers = combineReducers({
currentUserReducer, currentTokenReducer
})
export default allReducers
finally in index.js I have:
import React from 'react';
import b2cauth from 'react-azure-adb2c';
import ReactDOM from 'react-dom';
import jwt from 'jwt-decode'
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import {createStore} from 'redux';
import allReducers from './reducers';
import {Provider} from 'react-redux'
const store = createStore(allReducers);
and I guess proper encapsulation of App/ with Provider:
b2cauth.run(() => {
ReactDOM.render(<Provider store={store}><App /></Provider>, document.getElementById('root'));
serviceWorker.unregister();
In App.js I fire a gettoken function and want to store it both in local state and redux store:
componentDidMount (){
this.gettoken();
}
async gettoken(){
const dispatch = useDispatch();
let apiurl = 'https://get.....azurewebsites.net……'
var token = await Axios.get(apiurl,{headers: { 'Content-Type': 'application/x-www-form-urlencoded' }});
this.setState({accesstoken: token.data});
dispatch (settoken(token.data));
}
settoken is defined in src/actions/:
export const settoken = (token) => {
return {
type: 'SETTOKEN',
payload: token
};
};
When I deploy it I get:
Unhandled Rejection (Error): Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons: 1. You might have mismatching versions of React and the renderer (such as React DOM) 2. You might be breaking the Rules of Hooks 3. You might have more than one copy of React in the same app See ... for tips about how to debug and fix this problem.
And it points to this line in App.js:
const dispatch = useDispatch();
What am I doing wrong?
Upvotes: 2
Views: 2771
Reputation: 18183
You can't use a hook inside a class component
Please read the Rules of Hooks documentation
Call Hooks from React function components.
BTW, you don't need to have a GETTOKEN
action in your reducer because the token is already stored into the store.
const defaultState = {value: null};
const currentTokenReducer = (state = defaultState , action) => {
switch(action.type){
case 'SETTOKEN':
return {...state, value: action.payload};
default:
return state;
}
}
export default currentTokenReducer;
Then you don't need to create a internal state inside your component because you will retrieve the token from the store
import React, {useEffect} from 'react';
import { useSelector, useDispatch } from 'react-redux';
import axios from 'axios';
function AppComponent() {
const dispatch = useDispatch();
const token = useSelector(state => state.token.value);
useEffect(async () => {
const apiurl = 'https://get.....azurewebsites.net……';
const response = await axios.get(apiurl, ...);
dispatch({type: 'SETTOKEN', payload: response.data});
}, []);
return <div>{token}</div>;
}
In this example I used the hooks useDispatch
and useSelector
, you can find more information on theses hooks on the react-redux documentation
Upvotes: 2
Reputation: 4645
Would it be possible that you're trying to use a hook (useDispatch()
) inside a Class? Because hooks don't work inside classes (see: https://reactjs.org/docs/hooks-overview.html#but-what-is-a-hook).
You can still get dispatch
from your props with a good old connect(mapStateToProps)(App)
. (see: https://react-redux.js.org/using-react-redux/connect-mapdispatch#default-dispatch-as-a-prop)
Upvotes: 1