当&你在哪里清楚ReactJs的状态?

时间:2016-08-11 00:26:29

标签: javascript reactjs redux

我有这段代码

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: "", sharingKey: "" };
    }
    handleChange(event) {
        this.setState({ [event.target.name]: event.target.value });
    }
    validate() {
        if (this.state.storageName === "" && this.state.sharingKey == "") {
            console.log("validation error");
            return false;
        }
        this.props.createNewStorage(this.state);
    }
    resetForm() {
        this.setState({ storageName: "", sharingKey: "" })
        $(function () {
            Materialize.updateTextFields();
        });
    }
    render() {
        if (this.props.storages.openAddStorageModal) {
            $('#add-new-storage-modal').openModal({ dismissible: false });
        }
        else {
            $('#add-new-storage-modal').closeModal();
            this.resetForm( );
        }
        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" value={this.state.storageName} name="storageName" onChange={ (event) => this.handleChange(event) } />
                                <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"  value={this.state.sharingKey} name="sharingKey" onChange={ (event) => this.handleChange(event) }  />
                                <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" onClick={() => this.validate() }>Add</a>
                    <a href="#!" className="waves-effect waves-green btn-flat" onClick={() => this.props.loadAddStorageModal(false) }>Cancel</a>
                </div>
            </div>
        )
    }
}

我的orignal计划是每次我的模态对话框重新渲染我通过调用resetForm()方法重置表单值。

这不起作用,因为我得到关于&#34;改变状态的错误&#34;在渲染中,现在对我有意义,因为它会导致组件重新渲染。

但是这引出了我的问题,我在哪里清除状态呢?我正在尝试遵循redux模式。

我可以在&#34;验证()&#34;中进行清算。单击添加时的方法。

然而&#34; createNewStorage&#34;做ajax电话。如果ajax调用失败,我不确定如何处理这种情况。作为用户,我希望显示一条错误消息,但模式应该仍然以我输入的值打开。

如果需要,这是完整的代码。

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

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 />
         <div className="container">
          <StorageItemsContainer />
         </div>
        <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);

动作

export function fetchStorage() {
  return function(dispatch) {
      var payload = [
        {
            id: 1,
            name: "Fridge2",
            selected: true
        },
        {
            id: 2,
            name: "Closet2",
            selected: false
        },
        {
            id: 3,
            name: "Car2",
            selected: false
        }
    ];
     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 function selectStorage(storageId)
{
    return function(dispatch) {
         dispatch({type: "Select_Storage", payload: storageId});
    }
}

减速

export default function reducer(state = {
    fetchedStorages: [],
    openAddStorageModal: false,
    selectedStorage: null
}, action) {
    switch (action.type) {
        case "Fetch_Storage": {
            var selected;
            if(state.fetchedStorages != [])
            {
                selected =  action.payload[0]
            }
            return {
                fetchedStorages: action.payload,
                selectedStorage: selected
            }
        }
        case "Load_Add_Storage_Modal": {
            return {  
                openAddStorageModal: action.payload,
                fetchedStorages: state.fetchedStorages,
                selectedStorage: state.selectedStorage
            }
        }
        case "New_Storage_Created": {
            var lastStorage = state.fetchedStorages.slice(-1);  // just for now
            return {
                openAddStorageModal: false,
                fetchedStorages: state.fetchedStorages.concat({ id: lastStorage[0].id + 1,  name:  action.payload.storageName}),
                selectedStorage: state.selectedStorage
            }
        }
        case "Select_Storage": {
            var existingStorages =  state.fetchedStorages;
            var selectedStorage = null;
            for (var i = 0; i < existingStorages.length; i++) {
                 var storage = existingStorages[i];
                 if (action.payload == storage.id) {
                     storage.selected = true;
                     selectedStorage = storage;
                 }else{
                     storage.selected = false;
                 }
                 existingStorages[i] = storage;
            }
            return {
                fetchedStorages: existingStorages,
                selectedStorage: selectedStorage
            }

        }
    }


    return state;
}

2 个答案:

答案 0 :(得分:0)

是的,您只能在生命周期方法和setState中调用onEvents

在您的情况下,因为您依赖道具this.props.storages.openAddStorageModal

您可以在componentWillReceiveProps 生命周期方法中设置您的状态。

将使用nextProps值调用它,请注意此时未设置道具,您可以将nextProps参数与之前this.props中的道具进行比较

将此添加到您的组件,它应该可以正常工作:

componentWillReceiveProps(nextProps) {
  if (nextProps.storages.openAddStorageModal) {
      $('#add-new-storage-modal').openModal({ dismissible: false });
  } else {
      $('#add-new-storage-modal').closeModal();
      this.resetForm(); // will work fine here..
  }
}

答案 1 :(得分:0)

你应该有一个清除状态的动作 - dispatch(props.clearForm)

您的商店在收到活动事件时应负责清除其商店状态,从而触发重新呈现。

case CLEAR_FORM:
    // return new empty state object

您的表单应该根据商店的状态显示值,因此当重新呈现时,字段应为空。

如果您在每次击键时向商店写新值,则可能需要撤消操作事件,否则您可能会遇到性能问题。