I-PING Ou
I-PING Ou

Reputation: 507

javascript react-redux function

I am reading a tutorial on using redux to build a front end login-register-auth app. And I am not quite sure how protectedTest() funciton works in the following code. From what I understand, protectedTest in src/actions/index.js get called, it returns a function that will send a http request to server. However, when we call this.props.protectedTest in src/component/dashboard.js, how come we expect it to communicate with the server(the authoer claim that's what will happen) when it should only create a funciton that will do the job? Or is there something that I am missing here?

src/actions/index.js

import axios from 'axios';  
import { browserHistory } from 'react-router';  
import cookie from 'react-cookie';  
import { AUTH_USER,  
         AUTH_ERROR,
         UNAUTH_USER,
         PROTECTED_TEST } from './types';

const API_URL = 'http://localhost:3000/api';

export function errorHandler(dispatch, error, type) {  
  let errorMessage = '';

  if(error.data.error) {
    errorMessage = error.data.error;
  } else if(error.data{
    errorMessage = error.data;
  } else {
    errorMessage = error;
  }

  if(error.status === 401) {
    dispatch({
      type: type,
      payload: 'You are not authorized to do this. Please login and try again.'
    });
    logoutUser();
  } else {
    dispatch({
      type: type,
      payload: errorMessage
    });
  }
}

export function loginUser({ email, password }) {  
  return function(dispatch) {
    axios.post(`${API_URL}/auth/login`, { email, password })
    .then(response => {
      cookie.save('token', response.data.token, { path: '/' });
      dispatch({ type: AUTH_USER });
      window.location.href = CLIENT_ROOT_URL + '/dashboard';
    })
    .catch((error) => {
      errorHandler(dispatch, error.response, AUTH_ERROR)
    });
    }
  }

export function registerUser({ email, firstName, lastName, password }) {  
  return function(dispatch) {
    axios.post(`${API_URL}/auth/register`, { email, firstName, lastName, password })
    .then(response => {
      cookie.save('token', response.data.token, { path: '/' });
      dispatch({ type: AUTH_USER });
      window.location.href = CLIENT_ROOT_URL + '/dashboard';
    })
    .catch((error) => {
      errorHandler(dispatch, error.response, AUTH_ERROR)
    });
  }
}

export function logoutUser() {  
  return function (dispatch) {
    dispatch({ type: UNAUTH_USER });
    cookie.remove('token', { path: '/' });

    window.location.href = CLIENT_ROOT_URL + '/login';
  }
}

export function protectedTest() {  
  return function(dispatch) {
    axios.get(`${API_URL}/protected`, {
      headers: { 'Authorization': cookie.load('token') }
    })
    .then(response => {
      dispatch({
        type: PROTECTED_TEST,
        payload: response.data.content
      });
    })
    .catch((error) => {
      errorHandler(dispatch, error.response, AUTH_ERROR)
    });
  }
}

src/components/dashboard.js

import React, { Component } from 'react';  
import { connect } from 'react-redux';  
import * as actions from '../actions';

class Dashboard extends Component {

  constructor(props) {
    super(props);

    this.props.protectedTest();
  }

  renderContent() {
    if(this.props.content) {
      return (
        <p>{this.props.content}</p>
      );
    }
  }

  render() {
    return (
      <div>
        {this.renderContent()}
      </div>
    );
  }
}

function mapStateToProps(state) {  
  return { content: state.auth.content };
}

export default connect(mapStateToProps, actions)(Dashboard);  

Upvotes: 0

Views: 139

Answers (1)

Nik Markin
Nik Markin

Reputation: 981

how come we expect it to communicate with the server(the authoer claim that's what will happen) when it should only create a funciton that will do the job

Original redux library operates with simple javascript objects, yes. That means no async actions, since an application needs to know what action to execute immediately.

But, obviously, apps usually need to do some async operations, that's where redux-thunk comes in.

And it is used in the tutorial also, check the "Create index.js and enter the following:" section

// ...

import reduxThunk from 'redux-thunk';

// ...

const createStoreWithMiddleware = applyMiddleware(reduxThunk)(createStore);  
const store = createStoreWithMiddleware(reducers);

// ...

Redux thunk would invoke immediately any action function with a dispatch function where you would do some necessary async operations.

https://github.com/gaearon/redux-thunk/blob/master/src/index.js#L3

And after you received some results you would just dispatch a plain old action with received data.

dispatch({
    type: PROTECTED_TEST,
    payload: response.data.content
});

Here's a video I've found about redux-thunk: https://www.youtube.com/watch?v=1QI-UE3-0PU

Also the redux-thunk repository is well described in its readme file.

Upvotes: 1

Related Questions