8

react redux についてより深く理解するために、airbnb のリスティング フォームに似たダッシュボード フォームを開発しようとしていますが、プロジェクトの途中で立ち往生しています。ユーザーが続行ボタンをクリックすると、ユーザーが別のフォームに入力するなどの複数のフォームがあり、ユーザーが戻るボタンをクリックすると、ユーザーは以前に入力された値で1ステップ戻るフォームを取得します。私はこれのために何をすべきか決めることができませんでした。動作中のオブジェクトを、listingName として作成する必要がありますか。summary、name、email などを空の値として、Object.assign() などを使用して reducer で更新します。これまで、ユーザーが個人タブをクリックすると個人情報に関連するフォームが表示され、ユーザーが基本タブをクリックすると基本情報に関連するフォームが表示されるようにしか開発できませんでした。最後の送信時にすべてのフォームデータをサーバーに送信したい。私は今どうすればいい ?続行ボタンと戻るボタンに増分アクションと減分アクションを使用し、最後のフォーム ボタンに送信アクションを使用しますか? アイデアを教えてください。

ダッシュボードフォーム

これが私のコードです

アクション/index.js

export function selectForm(form){
  return{
    type: 'FORM_SELECTED',
    payload: form
  };

}

レデューサー/reducer_active_form.js

export default function(state=null, action){
  let newState = Object.assign({},state);
  switch(action.type){
    case 'FORM_SELECTED':
      return action.payload;
  }
  return state;
}

レデューサー/reducer_form_option.js

export default function(){
  return[
    { option: 'Personal Information', id:1},
    { option: 'Basic Information', id:2 },
    { option: 'Description', id:3},
    { option: 'Location', id:4},
    { option: 'Amenities', id:5},
    { option: 'Gallery', id:6}
  ]
}

コンテナー/フォームの詳細

class FormDetail extends Component{
  renderPersonalInfo(){
    return(
      <div className="personalInfo">
        <div className="col-md-4">
          <label htmlFor='name'>Owner Name</label>
          <input ref="name" type="textbox" className="form-control" id="name" placeholder="Owner name" />
        </div>

        <div className="col-md-4">
          <label htmlFor="email">Email</label>
          <input ref="email" type="email" className="form-control" id="email" placeholder="email" />
        </div>

        <div className="col-md-4">
          <label htmlFor="phoneNumber">Phone Number</label>
          <input ref="phone" type="textbox" className="form-control" id="phoneNumber" placeholder="phone number" />
        </div>

        <div className="buttons">
          <button className="btn btn-primary">Continue</button>
        </div>

      </div>
      );
  }

  renderBasicInfo(){
    return(
       <div>
              <h3>Help Rent seekers find the right fit</h3>
              <p className="subtitle">People searching on Rental Space can filter by listing basics to find a space that matches their needs.</p>
              <hr/>
              <div className="col-md-4 basicForm">
                  <label htmlFor="price">Property Type</label>
                  <select className="form-control" name="Property Type" ref="property">
                      <option value="appartment">Appartment</option>
                      <option value="house">House</option>
                  </select>
              </div>
              <div className="col-md-4 basicForm">
                  <label htmlFor="price">Price</label>
                  <input type="textbox" ref="price" className="form-control" id="price" placeholder="Enter Price" required />
              </div>
              <div className="buttons">
                <button className="btn btn-primary">Back</button>
                <button className="btn btn-primary">Continue</button>
              </div>
            </div>
      );
  }

  renderDescription(){
    return(
        <div>
            <h3>Tell Rent Seekers about your space</h3>
            <hr/>
            <div className="col-md-6">
                <label htmlFor="listingName">Listing Name</label>
                <input ref="name" type="textbox" className="form-control" id="listingName" placeholder="Be clear" />
            </div>
            <div className="col-sm-6">
                <label htmlFor="summary">Summary</label>
                <textarea ref="summary" className="form-control" id="summary" rows="3"></textarea>
            </div>
             <div className="buttons">
                <button className="btn btn-primary">Back</button>
                <button className="btn btn-primary">Continue</button>
             </div>
        </div>
      );
  }

  renderLocation(){
    return(
        <div>
            <h3>Help guests find your place</h3>
            <p className="subtitle">will use this information to find a place that’s in the right spot.</p>
            <hr/>
            <div className="col-md-6">
                <label htmlFor="city">City</label>
                <input ref="city" type="textbox" className="form-control" id="city" placeholder="Biratnagar" />
            </div>
            <div className="col-md-6">
                <label htmlFor="placeName">Name of Place</label>
                <input ref="place" type="textbox" className="form-control" id="placeName" placeholder="Ganesh Chowk" />
            </div>
             <div className="buttons">
                <button className="btn btn-primary">Back</button>
                <button className="btn btn-primary">Continue</button>
             </div>
        </div>
      );
  }

  render(){
    if ( !this.props.form){
      return this.renderPersonalInfo();
    }

    const type = this.props.form.option;
    console.log('type is', type);

    if ( type === 'Personal Information'){
      return this.renderPersonalInfo();
    }

    if ( type === 'Basic Information'){
      return this.renderBasicInfo();
    }

    if ( type === 'Description'){
      return this.renderDescription();
    }

    if ( type === 'Location'){
      return this.renderLocation();
    }
}
}

function mapStateToProps(state){

  return{
    form: state.activeForm
  };
}

export default connect(mapStateToProps)(FormDetail);
4

2 に答える 2

6

最初に欠けているのは、制御されたコンポーネントです。value入力にプロパティと関数を与えることで、onChange入力を外部状態にリンクします。

コンポーネントは、react-redux を介して、必要な状態とアクションにアクセスできる必要があります。valueフォームのは、そのオブジェクトの状態である必要があります。したがって、次のような状態になる可能性があります。

location: {
  listingName: '123 Main St',
  summary: 'The most beautiful place!'
}

次に、各プロパティを入力に渡すだけです。locationこの例では、 prop を に渡し、関連するすべてのアクションをmapStateToProps含むオブジェクトを に渡していると仮定しています。actionsmapDispatchToProps

changeHandler(ev, fieldName) {
  const val = ev.target.value;
  this.props.actions.updateField(fieldName, val);
},

render() {
  return (
    <input 
      value={this.props.location.listingName} 
      onChange={(ev) => { this.changeHandler(ev, 'listingName'}} 
    />
  );
}

状態を更新するために使用できるアクションを提供します。

function updatefield(field, val) {
  return {
    type: UPDATE_FIELD,
    field,
    val
  };
}

次に、レデューサーでそれをマージするだけです

switch (action.type) {
  case UPDATE_FIELD:
    state = { ...state, [action.field]: val };

(きちんとするために動的キーとスプレッド演算子を使用しますが、Object.assign に似ています)

フォームの状態はすべて、この方法で Redux ストアに保存されます。そのデータをサーバーに送信する準備ができたら、redux-thunkで非同期アクションを使用するか、呼び出しを実行するミドルウェアをセットアップできます。いずれにせよ、戦略は同じです。状態はローカルで持続し、すべてのフォームに入力され、ユーザーが送信するとサーバーに送信されます。

私はこれをかなり簡単に説明しました。何か詳しく説明する必要がある場合はお知らせください:)

于 2016-03-06T03:39:54.003 に答える
1

react-redux を使用しているため、redux-form を使用できます。作業負荷を軽減し、バグがない (私の知る限り) ため、コーディングに大いに役立ちます。私の意見では、できるだけ機敏になりたいので、提供されているすべてのライブラリ/フレームワークを使用したいと思うでしょう。

また、redux-form にはウィザード フォームの実装があります。それがまさにあなたが探しているものだと思います。

http://erikras.github.io/redux-form/#/examples/wizard?_k=yspolv

リンクをたどるだけで、実装方法に関する非常に優れたチュートリアルが表示されます。簡単なはずです。

于 2016-03-06T02:02:14.883 に答える