Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to properly implement mapStateToProps using Redux?

Tags:

reactjs

redux

I'm trying to do something really simple: Each time you click a button the value of 'current' in this component: https://github.com/conorhastings/react-thermometer increases.

The problem is that when I build, the console throws the following error: Module build failed: SyntaxError: Unexpected token, expected ( (29:11)

in this line:

function mapStateToProps(state){

Here's the entire code of my container:

import React, {Component} from 'react';
import Thermometer from "react-thermometer";
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {incrementValue} from '../actions/index';

class Thermo extends Component{
  getValue(){
    return this.props.val;
  }

  render(){
    return(
          <div>
              <Thermometer
                      min={0}
                      max={90}
                      width={10}
                      height={90}
                      backgroundColor={'gray'}
                      fillColor={'pink'}
                      current={this.getValue()}
              />
              <Button onClick={() => this.props.incrementValue(val)}>+</Button>
          </div>
    )
  }

  function mapStateToProps(state){
    return{
      val: state.val
    };
  }

  function matchDispatchToProps(dispatch){
    return bindActionCreators({incrementValue: incrementValue}, dispatch);
  }
}

export default connect(mapStateToProps, matchDispatchToProps)(Thermo);

And just in case, this is my webpack config:

var path = require('path');
var webpack = require('webpack');

module.exports = {
    devServer: {
        inline: true,
        contentBase: './src',
        port: 3000
    },
    devtool: 'cheap-module-eval-source-map',
    entry: './dev/js/index.js',
    module: {
        loaders: [
            {
                test: /\.js$/,
                loaders: ['babel'],
                exclude: /node_modules/
            },
            {
                test: /\.scss/,
                loader: 'style-loader!css-loader!sass-loader'
            }
        ]
    },
    output: {
        path: 'src',
        filename: 'js/bundle.min.js'
    },
    plugins: [
        new webpack.optimize.OccurrenceOrderPlugin()
    ]
};
like image 700
user3235483 Avatar asked Dec 10 '16 08:12

user3235483


People also ask

What does mapStateToProps do in Redux?

As the first argument passed in to connect , mapStateToProps is used for selecting the part of the data from the store that the connected component needs. It's frequently referred to as just mapState for short. It is called every time the store state changes.

What is mapStateToProps and mapDispatchToProps in React Redux?

The mapStateToProps and mapDispatchToProps deals with your Redux store's state and dispatch , respectively. state and dispatch will be supplied to your mapStateToProps or mapDispatchToProps functions as the first argument.

Can I use Redux with functional components?

React Redux in functional components. The useAppSelector is used to read a value from the store state, and it also subscribes to the state's updates. The useDispatch Hook is used to dispatch actions to the reducer functions.

What do you return out of mapStateToProps?

In particular mapStateToProps() . The way I understand it, the return value of mapStateToProps will be an object derived from state (as it lives in the store), whose keys will be passed to your target component (the component connect is applied to) as props.


1 Answers

Put the functions outside the class:

import React, {Component} from 'react';
import Thermometer from "react-thermometer";
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {incrementValue} from '../actions/index';

class Thermo extends Component{
  getValue(){
    return this.props.val;
  }

  render(){
    return(
          <div>
              <Thermometer
                      min={0}
                      max={90}
                      width={10}
                      height={90}
                      backgroundColor={'gray'}
                      fillColor={'pink'}
                      current={this.getValue()}
              />
              <Button onClick={() => this.props.incrementValue(val)}>+</Button>
          </div>
    )
  }


}

function mapStateToProps(state){
    return{
      val: state.val
    };
  }

  function mapDispatchToProps(dispatch){
    return bindActionCreators({incrementValue: incrementValue}, dispatch);
  }

export default connect(mapStateToProps, matchDispatchToProps)(Thermo);

You are passing the definition of your component to the function returned by connect, hence you don't make an instance of that class at any time. The mapStateToProps and mapDispatchToProps are completely independent of your class, and are used before any instance of Thermo is made. Thus you need to have them outside.

like image 192
martinarroyo Avatar answered Oct 29 '22 13:10

martinarroyo