erikras / react-redux-universal-hot-example

A starter boilerplate for a universal webapp using express, react, redux, webpack, and react-transform
MIT License
11.99k stars 2.5k forks source link

An action is not dispatching #1393

Open ycruzb opened 7 years ago

ycruzb commented 7 years ago

Hi all !!! I've created a new redux module called portfolio.js, here is the content of the module:

const INCREMENTPORTFOLIO = 'redux-example/portfolio/INCREMENTPORTFOLIO';
const LOAD = 'redux-example/portfolio/LOAD';
const LOAD_SUCCESS = 'redux-example/portfolio/LOAD_SUCCESS';
const LOAD_FAIL = 'redux-example/portfolio/LOAD_FAIL';
const INCLIKE = 'redux-example/portfolio/INCLIKE';

const initialState = {
  counter: 74,
  loaded: false,
  list: []
};

export default function portfolio(state = initialState, action = {}) {
  switch (action.type) {
    case LOAD:
      return {
        ...state,
        loading: true
      };
    case LOAD_SUCCESS:
      return {
        ...state,
        loading: false,
        loaded: true,
        list: action.result
      };
    case LOAD_FAIL:
      return {
        ...state,
        loading: false,
        loaded: false,
        error: action.error
      };
    case INCLIKE:
      return state;
    case INCREMENTPORTFOLIO:
      const {counter} = state;
      return {
        ...state,
        counter: counter + 1
      };
    default:
      return state;
  }
}

export function incrementportfolio() {
  return {
    type: INCREMENTPORTFOLIO
  };
}

export function isLoaded(globalState) {
  return globalState.portfolio && globalState.portfolio.loaded;
}

export function load() {
  return {
    types: [LOAD, LOAD_SUCCESS, LOAD_FAIL],
    promise: (client) => client.get('/loadPortfolio')
  };
}

export function inclike(index) {
  return {
    type: INCLIKE,
    payload: {
      index: index
    }
  };
}

then I have included it properly in reducer.js inside redux/modules and then I have created a component called PorfolioList.js with this code:

import React, {Component, PropTypes} from 'react';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {incrementportfolio} from 'redux/modules/portfolio';

@connect(
    state => ({counter: state.portfolio.counter}),
    dispatch => bindActionCreators({incrementportfolio}, dispatch))
export default class PortfolioList extends Component {
  static propTypes = {
    counter: PropTypes.number,
    incrementportfolio: PropTypes.func.isRequired
  }

  render() {
    const {counter} = this.props;
    return (
      <button className="btn btn-default" onClick={incrementportfolio}>
        You have clicked me {counter} time{counter === 1 ? '' : 's'}.
      </button>
    );
  }
}

I have included this component properly in components/index.js and here comes the issue, the component is rendered well in the page and the button shows the initial value but the onclick doesn't fires the action. In redux dev tools I dispatch manually the action and the state is modified correctly. Why the onclick of the button is not firing the action ? Can you help me please ??

ananddodia commented 7 years ago

In button onClick event is not properly bind to function. this line: button className="btn btn-default" onClick={incrementportfolio}> change to: button className="btn btn-default" onClick={this.props.incrementportfolio}>

OR

this line: const {counter} = this.props; change to: const {counter, incrementportfolio} = this.props;

ycruzb commented 7 years ago

Hi ananddodia, thanks very much for your help. I initially typed this:

const {counter, incrementportfolio} = this.props;

but it gives me this error:

16:21 error "incrementportfolio" is already declared in the upper scope no-shadow

it is weird, does it ? because of that I decided to write this line in that way but I'll test your other option.

Thanks a lot, I'll give you the result of the test.

ycruzb commented 7 years ago

It works like a charm !!

... button className="btn btn-default" onClick={this.props.incrementportfolio}>

it works !! but the question is why I get this error ?

16:21 error "incrementportfolio" is already declared in the upper scope no-shadow

Why I can't to get incrementportfolio in this way ?

const {counter, incrementportfolio} = this.props;

Can you answer this question ?

Thanks in advance

parth-choudhary commented 7 years ago

Because you have import {incrementportfolio} from 'redux/modules/portfolio'; in your code already.

So by doing const {counter, incrementportfolio} = this.props; you are redefining with same name.

ananddodia commented 7 years ago

@ycruzb sorry for late reply I am stuck in other work(Using this repo. I am trying to implement code split based on modules so only necessary js css are loaded and not one single js css.) helping hands are appreciated. But whatever @parth-choudhary said is absolutely right. Thank you @parth-choudhary. @ycruzb you can if you still dont wan to change this line: const {counter, incrementportfolio} = this.props; than you can call portfolio all export function in one single object and then access by .(dot) operator.

change to this: import * as portfolio from 'redux/modules/portfolio'; So now you can access any function like wise portfolio.functionName (ex. portfolio.incrementportfolio and portfolio.isLoaded and so on.) Hope you are getting what I mention. if not, can get back to me. :-)