0

I not 100% sure if I am doing this right as per the redux design.

import React from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import 'materialize-css/sass/materialize.scss';
import NavigationContainer from './NavigationContainer';

import AddStorageModal from './AddStorageModal.js'
import {loadAddStorageModal, createNewStorage} from '../actions/StorageActions.js'
import '../styles/main.scss';


class App extends React.Component {
  render() {
    return (
      <div>
        <NavigationContainer />
        <AddStorageModal {...this.props} />
      </div>
    )
  }
}

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

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


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

StorageActions

export function fetchStorage() {
  return function(dispatch) {
      var payload = [
        {
            id: 1,
            name: "Fridge2"
        },
        {
            id: 2,
            name: "Closet2"
        },
        {
            id: 3,
            name: "Car2"
        }
    ];
     dispatch({type: "Fetch_Storage", payload: payload});
  }
}

export function loadAddStorageModal(load) {
    return function(dispatch) {
         dispatch({type: "Load_Add_Storage_Modal", payload: load});
    }
}

export function createNewStorage(storage) {
    return function(dispatch) {
         dispatch({type: "New_Storage_Created", payload: storage});
    }
}

Reducer

export default function reducer(state = {
    fetchedStorages: [],
    openAddStorageModal: false
}, action) {
    switch (action.type) {
        case "Fetch_Storage": {
            return {
                fetchedStorages: action.payload
            }
        }
        case "Load_Add_Storage_Modal": {
            return {  
                openAddStorageModal: action.payload,
                fetchedStorages: state.fetchedStorages
            }
        }
        case "New_Storage_Created": {
            return {
                openAddStorageModal: false,
            }
        }
    }


    return state;
}

AddStorageModal

import React from 'react';

import 'materialize-css/sass/materialize.scss';
import 'materialize-css/js/materialize.js';
import 'font-awesome/scss/font-awesome.scss';
import '../styles/main.scss';

export default class AddStorageModal extends React.Component {
    constructor() {
        super();
        this.state = {storageName: ""}
    }
    handleChange(event) {
       this.setState({storageName: event.target.value});
    }
    render() {
        if (this.props.storages.openAddStorageModal) {
            $('#add-new-storage-modal').openModal({ dismissible: false });
        }
        return (
            <div id="add-new-storage-modal" className="modal" >
                <div className="modal-content">
                    <h6>Enter your new Storage (Freezer, Pantry, etc.) </h6>
                    <div className="row">
                        <form>
                            <div className="input-field col s12 m12 l12 ">
                                <input id="storage_name" type="text" className="validate" value={this.state.storageName}  onChange={this.handleChange} />
                                <label htmlFor="storage_name">Storage Name</label>
                            </div>
                            <br />
                            <h4 className="center">OR</h4>
                            <h6>Enter in the sharing key you were given.</h6>
                            <div className="input-field col s12 m12 l12 ">
                                <input id="sharing_key" type="text" className="validate" />
                                <label htmlFor="sharing_key">Sharking Key</label>
                            </div>
                        </form>
                    </div>
                </div>
                <div className="modal-footer">
                    <a href="#!" className="waves-effect waves-green btn-flat left">Add</a>
                    <a href="#!" className="modal-action modal-close waves-effect waves-green btn-flat" onClick={() => this.props.loadAddStorageModal(false) }>Cancel</a>
                </div>
            </div>
        )
    }
}

I get

Uncaught TypeError: Cannot read property 'setState' of undefined

So I am not sure if this just means I am doing redux wrong or if I just made some general error.

1
  • you just forgot to bind handleChange, add this.handleChange = this.handleChange.bind(this) to the constructor Commented Aug 9, 2016 at 20:35

2 Answers 2

2

You can't pass a generic function reference, you need to keep the reference to this. You have 2 options:

  1. bind this to the function, like @nuway said in his answer.

  2. Use an arrow function, which also keeps the this reference: onChange={ (event) => this.handleChange(event) }

Sign up to request clarification or add additional context in comments.

5 Comments

Yea. I just saw that. On a side note as I am setting setState is there away to just make one handleChange event for all my setting of state? I don't want to write a function for each input.
I also tried this "arrow function" but I get "Cannot read property 'target' of undefined"
@chobo2 yes you can make one function. if you need to know which element it's coming from, you can check the event argument. it should have the target in it.
@nuway - Yep was able to do that with target.name. I was unable to get the arrow function working not sure why though.
@chobo2 Check my edit, I've added the event parameter. At first I just wrote generically, but when you're using handlers you should pass the events, it will work for you now.
0

you need to bind to this for the handleChange handler, otherwise this inside handleChange funtion won't be the react component but rather the input element itself.

onChange={this.handleChange.bind(this)}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.