Reactjs并使用Redux进行表单处理

时间:2017-08-23 18:22:15

标签: reactjs redux

我是redux的新手,我正在尝试重新构建一个旧的应用程序 - 因此第一页将向用户显示可能的启动画面,然后登录表单 - 并且在成功登录时 - 向用户显示主网站。

我想帮助对antd表单和redux处理/处理进行登录验证处理。加强这些演示。类似问题的链接 - 细分等等......可能遇到的常见问题等等 - 甚至可能退回功能。

我有这些旧组件,所以这就是应用程序的外观。我很可能会使用antd作为表单组件。

这是一个我使用redux的演示 - 但这只是从api获取数据 - 然后渲染它 - 我热衷于挑选这部分代码来替换部分表单处理等。

这个redux演示在这个jsfiddle上供参考。

http://jsfiddle.net/0ht35rpb/104/

// redux demo

import React, { Component } from 'react'
import { render } from 'react-dom'
import {Provider, connect} from 'react-redux'
import {createStore, applyMiddleware} from 'redux' 
import thunk from 'redux-thunk';

import MapChart from './modules/mapChart/MapChart'
import './index.css'

function fetchPostsRequest(){
  return {
    type: "FETCH_REQUEST"
  }
}

function fetchPostsSuccess(payload) {
  return {
    type: "FETCH_SUCCESS",
    payload
  }
}

function fetchPostsError() {
  return {
    type: "FETCH_ERROR"
  }
}

const reducer = (state = {}, action) => {
  switch (action.type) {
    case "FETCH_REQUEST":
      return state;
    case "FETCH_SUCCESS": 
      return {...state, posts: action.payload};
    default:
      return state;
  }
} 

function fetchPostsWithRedux() {
  return (dispatch) => {
    dispatch(fetchPostsRequest());
    return fetchPosts().then(([response, json]) =>{
      if(response.status === 200){
        dispatch(fetchPostsSuccess(json))
      }
      else{
        dispatch(fetchPostsError())
      }
    })
  }
}

function fetchPosts() {
  const URL = 'https://data.police.uk/api/crimes-street/all-crime?poly=52.268,0.543:52.794,0.238:52.130,0.478&date=2017-01';
  return fetch(URL, { method: 'GET'})
     .then( response => Promise.all([response, response.json()]));
}

// this is how you'll get your icon links
// instead of a switch with loads of repetitive bytes
const iconMap = {
  'anti-social-behaviour':  'green-dot',
  'burglary':               'red-dot',
  'other-theft':            'pink-dot',
  'public-order':            'purple',
  'robbery':                 'yellow',
  'vehicle-crime':          'orange',
  'violent-crime':          'orange-dot',
  'other-crime':            'ltblue-dot',
  'criminal-damage-arson':  'yellow-dot',
  'drugs':                  'purple-dot',
  'shoplifting':            'blue-dot'
}

// this is a class because it needs state
class CrimeMap extends Component {
  state = {
    markers: []
  }

  componentDidMount() {    
    this.props.fetchPostsWithRedux()
  }

  componentWillReceiveProps(nextProps){
    this.setState({markers: this.mapLayerData(nextProps.posts)});
  }

  // store only the data you want to pass as props to each Marker
  // instead of mapping it directly in MapChart every time it renders
  mapLayerData(markers) {
    // use a standard map function instead of $.each
    // destructuring saves time and repetition
    return markers.map(({ category, location }) => ({
      // use a template string and a simple map of icon names to get your icon uri
      icon: 'http://maps.google.com/mapfiles/ms/icons/'+ iconMap[category] +'.png',
      label: category,
      name: category,
      position: {
        lat: location.latitude,
        lng: location.longitude
      }
    }))
  }

  render() {
    // there's only one layer, so render it directly
    return (
      <div className="app">
        <MapChart markers={this.state.markers} />
      </div>
    )
  }
}

function mapStateToProps(state){
  return {
    posts: state.posts
  }
}    

let Container = connect(mapStateToProps, {fetchPostsWithRedux})(CrimeMap);

const store = createStore(
    reducer,
    applyMiddleware(thunk)
);

render(
    <Provider store={store}>
      <Container/>
    </Provider>,
    document.getElementById('root')
);

这里是带有旧代码的jsfiddle - 如果它有助于证明那里的变化/改进。

http://jsfiddle.net/0ht35rpb/103/

//旧代码

import React from 'react';
import ReactDOM from 'react-dom';

//splash page
var SplashPage = React.createClass({
  componentDidMount: function() {

    function animateSplash(){
      $('.splash-page').animate({
        opacity: 0,
      }, 2500, "linear", function() {
        // Animation complete.
        $('.splash-page').hide();
      });
    }

    setTimeout(function(){ 
      animateSplash();
    }, 4000);

  },
  render: function() {
    return (
      <div className="splash-page">
        <div className="content">
          <div className="splash">
            SPLASH PAGE
          </div>
        </div>
      </div>
    );
  }
});


//form page
var LandingForm = React.createClass({
  componentDidMount: function(){

  },
  getInitialState: function() {
    return {postcode: '', propertytype: '', propertysize: '', propertytypename: '', isValid: false};
  },
  checkPostCodeValid: function(target, postcode){

    var host = this.props.source[0]["local"];
    if(window.location.hostname != "localhost"){
        host = this.props.source[0]["live"];
    }

    var isPostcodeValidApiCall = host + 'codeigniter/index.php/api/isPostcodeValid/'+postcode;

    //quick hack to bypass email validator on computer with no db
    if(window.location.hostname == "localhost"){
      isPostcodeValidApiCall = host + "_test_emailvalidate_json1_nw1.php";
    }

    var that = this;

    this.serverRequest = $.get(isPostcodeValidApiCall, function (response) {
        var response = JSON.parse(response);
        var errorMsg = response.isPostcodeValid.errorMessage;
        var isValid = response.isPostcodeValid.isValid;

        if(!isValid){
          //show error message
          setLabelError(target, errorMsg, true);//target, error message, show error
        }
        else{
          //do not show error
          setLabelError(target, errorMsg, false);//target, error message, show error
        } 

        that.setState({
          isValid: isValid
        });
     }.bind(this));

  },
  handlePostcodeChange: function(e) {
    this.setState({postcode: e.target.value});        
  },
  handleValidation: function(e){
    //do a check on char lengths greater than 1
    if((e.target.value).length > 1){
      this.checkPostCodeValid(e.target, e.target.value);
    }
  },
  handlePropertyTypeChange: function(val) {
    this.setState({propertytypename: val.label});
    this.setState({propertytype: val.value});
    setReactSelectorLabel(val);
  },
  handlePropertySizeChange: function(val) {
    this.setState({propertysize: val.value});
    setReactSelectorLabel(val);
  },
  handleSubmit: function(e) {
    e.preventDefault();
    var postcode = this.state.postcode.trim().toUpperCase();
    var propertytype = this.state.propertytype.trim();
    var propertysize = this.state.propertysize.trim();
    var isValid = this.state.isValid;
    //console.log("isValid", isValid);

    var propertytypename = this.state.propertytypename.trim();
    if (!postcode || !propertytype || !propertysize || !isValid) {
      return;
    }
    // TODO: send request to the server

    this.setState({postcode: '', propertytype: '', propertysize: '', propertytypename: '', isValid: false});

    var shortPostcode = ((postcode.substring(0, postcode.length-3)).trim());
    var postCodeSector = ((postcode.substring(0, postcode.length-2)).trim());

    //build queries
      var masterApiCall = '/api/master/'+shortPostcode+'/'+propertytype+'/'+propertysize;
      var directApiCall = '/api/direct/'+postcode;

      var dataEntry = [
        {
          "directApiCall" : directApiCall,
          "masterApiCall": masterApiCall,
          "postCodeSector": postCodeSector,
          "postCode": shortPostcode,
          "fullPostCode": postcode,
          "propertyType": propertytype,
          "propertySize": propertysize,
          "propertyTypeName": propertytypename
        }
      ];

    ReactDOM.render(
      <DataPage root={initConfig} source={dataEntry} />,
      document.getElementById('root'),
      function() {
        //xx
      }
    );

  },
  componentWillUnmount: function() {
    this.serverRequest.abort();
  },
  render: function() {

      var optionsPropertyType = [
        { value: 'val1', label: 'key1' },
        { value: 'val2', label:'key2'}
      ];                  

      var optionsPropertySize = [
        { value: 'val1', label: 'key1' },
        { value: 'val2', label:'key2'}
      ];

    return (

    <div className="container" data-role="screenbackground">

      <div className="row">

        <div className="col-md-12 col">

          <div className="form-components">  

            <form id="mainform" data-role="form-aesethetics" className="commentForm" onSubmit={this.handleSubmit}>
              <fieldset>
                <label>Postcode</label>
                <input 
                  placeholder="Postcode"
                  type="text" 
                  name="postcode"
                  value={this.state.postcode}
                  onChange={this.handlePostcodeChange}
                  onKeyPress={this.handleValidation}
                />
              </fieldset>

              <fieldset>
                <label>Property Type</label>

                <Select
                    name="propertytype"
                    value={this.state.propertytype}
                    options= {optionsPropertyType}
                    onChange={this.handlePropertyTypeChange}
                    placeholder="Property type"
                />

              </fieldset>

              <fieldset>
                <label>Property Size</label>

                <Select
                    name="propertysize"
                    value={this.state.propertysize}
                    options= {optionsPropertySize}
                    onChange={this.handlePropertySizeChange}
                    placeholder="Property size"
                />

              </fieldset>

              <fieldset className="aligninmobile">
                <input type="submit" disabled={!this.state.isValid} value="Let's Go"/>
              </fieldset>
            </form>
          </div>

        </div>

      </div>

    </div>

    );
  }
});



//Data Page
var DataPage = React.createClass({

    getInitialState: function() {
      return {
        rawDirectData: ''
      };
    },

    componentDidMount: function () {
        //check host to see which source to use
        var host = this.props.root[0]["local"];
        if(window.location.hostname != "localhost"){
            host = this.props.root[0]["live"];
        }

        var directApi = host + this.props.source[0]["directApiCall"];

        if(window.location.hostname == "localhost"){
            directApi = host + "_test_direct_json1_nw1.php";
        }

        var that = this;
        function requestData(source, callback){
            that.serverRequest = $.get(source, function (response) {
                callback(response);
            }.bind(that));    
        }

        requestData(directApi, function(rawDirectData){
            that.setState({
              rawDirectData: JSON.parse(rawDirectData)
            }); 
        });

    },

    componentWillUnmount: function() {
      this.serverRequest.abort();
    },


  render: function() {
    var props = this.props;

    var directApiData = this.state.rawDirectData;

    return (
      <div className="container">
          <div className="row">
              <div className="col-md-12 col">
                  <MultipleComponents root={props.root} source={props.source} />
              </div>
              <div className="col-md-12 col">
                  <ContactForm root={props.root} source={props.source} data={directApiData}/>
              </div>
          </div>
      </div>
    );
  }
});


//LandingForm
ReactDOM.render(
  <div>
    <SplashPage />
    <LandingForm source={initConfig} />
  </div>,
  document.getElementById('root'),
  function(){ 
  }
);

0 个答案:

没有答案