2016-08-09 2 views
0

Я не уверен на 100%, если я делаю это правильно в соответствии с дизайном redux.Как подключить поля ввода к Reactjs/Redux?

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}); 
    } 
} 

Редуктор

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> 
     ) 
    } 
} 

Я получаю

Uncaught TypeError: Cannot read property 'setState' of undefined 

Так что я не уверен, что это означает, что я делаю редукцию неправильно или я просто сделал некоторую общую ошибку.

+0

вы просто забыли связать handleChange, добавьте 'this.handleChange = this.handleChange.bind (это)' конструктору – QoP

ответ

2

Вы не можете передать общую ссылку на функцию, необходимо сохранить ссылку на this. У вас есть 2 варианта:

  1. связывают this к функции, как @nuway сказал в своем ответе.

  2. Используйте функцию стрелки, которая также держит this ссылка: onChange={ (event) => this.handleChange(event) }

+0

Да. Я просто это видел. На боковой ноте, когда я устанавливаю setState, можно просто сделать одно событие handleChange для всех моих настроек состояния? Я не хочу писать функцию для каждого входа. – chobo2

+0

Я также пробовал эту «функцию стрелки», но я получаю «Не могу прочитать свойство« цель »неопределенного« – chobo2

+0

@ chobo2 да, вы можете сделать одну функцию. если вам нужно знать, из какого элемента он исходит, вы можете проверить аргумент события. он должен иметь в себе цель. – nuway

0

вам нужно привязать к this для обработчика handleChange, в противном случае this внутри handleChange Funtion не будет компонент, а скорее входной сам элемент реагирует.

onChange={this.handleChange.bind(this)} 
Смежные вопросы