8

我一直在尝试开发一个类似于 airbnb 列表表单的仪表板表单,以更深入地了解 react redux,但我被困在我的项目中间。我有一个多重表单,当用户单击继续按钮时,用户将获得另一个表单来填写,依此类推,如果用户单击后退按钮,用户将获得一个带有先前填充值的表单。我无法决定我应该为此做些什么。我是否必须创建一个正在运行的对象作为 listingName 。摘要,姓名,电子邮件等作为空值,并使用 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!'
}

然后,您只需将每个属性传递给输入。在这个例子中,我假设你已经传递了locationprop in mapStateToProps,以及一个actions包含所有相关操作的对象mapDispatchToProps

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 回答