Reputation: 265
I am using JWT auth, when the user log in I store the token in the localstorage. How do I fetch the api with that token, so I can get the user details when the page loads for the first time.
I'm already using React Thunk for the async requests but I don't know how to set the initialState with an async request. However is it okay to set the localstorage in the reducers?
Upvotes: 0
Views: 3358
Reputation: 162
You would want to do something like this in your action:
import axios from 'axios';
export const LOADING = "LOADING";
export const SUCCESS = "SUCCESS";
export const FAILURE = "FAILURE";
export const UPDATE = "UPDATE";
export const SUCCESSFUL_UPDATE = "SUCCESSFUL_UPDATE";
export const getSmurfs = () => dispatch => {
dispatch({ type: LOADING })
axios.get('http://localhost:3333/smurfs')
.then(res => dispatch({ type: SUCCESS, payload: res.data}))
.catch(err => dispatch({ type: FAILURE, payload: err}))
}
So you would start with a state of Loading which would change to Success or Failure depending on the response. Then in your reducer you would want to do something like:
import { LOADING, SUCCESS, FAILURE, UPDATE, SUCCESSFUL_UPDATE } from '../actions/index';
const initialState = {
smurfs: [],
loading: false,
error: "",
updateID: "",
clicked: false,
update: []
}
export default function reducer(state= initialState, action) {
switch(action.type) {
case LOADING:
return {
...state,
smurfs: [],
loading: true,
err: ''
}
case SUCCESS:
return {
...state,
smurfs: action.payload,
loading: false,
err: ''
}
Basically when it is successful it will turn off the loading and display your returned data
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { getSmurfs, deleteSmurf, update } from '../actions/index';
import Smurfs from './smurfs';
import Form from './form';
import UpdateForm from './updateForm';
class SmurfsViewer extends Component {
componentDidMount() {
this.props.getSmurfs()
}
render() {
console.log(this.props.smurfs)
// if loading returns true then display loading smurfs..
if(this.props.loading) {
return (<h1>LOADING SMURFS....</h1>)
}
//if clicked resolves true then display the form to allow updating of the smurf that had its edit button clicked
let form;
if(this.props.clicked) {
form = <UpdateForm />
} else {
form = <Form />
}
return(
<div>
<Smurfs smurfs={this.props.smurfs} deleteSmurf={this.props.deleteSmurf} update={this.props.update}/>
{form}
</div>
)
}
}
const mstp = state => {
console.log("FROM VIEWER:", state)
return {
smurfs: state.smurfs,
loading: state.loading,
clicked: state.clicked
}
}
export default connect(mstp, { getSmurfs, deleteSmurf, update })(SmurfsViewer);
So you need to send the state from Redux through the mapStateToProps(mstp) and connect methods. Then you can use them in the component and it will update your redux state as needed. Then just refer to them as this.props.getSmurfs or something along those lines
Upvotes: 2