javascript - 更新表单中的数据。保持可编辑状态。 (与 Redux react ,无 redux-form)

标签 javascript forms reactjs redux react-redux

问题

enter image description here

我有一份人员名单。我想要:

  1. 点击姓名选择要编辑的用户。
  2. 编辑该用户的信息,以便我可以点击提交按钮并更新列表。
  3. 如果我点击其他姓名,我想切换到该人的信息,而无需先特意关闭表单。

enter image description here

一切正常,直到#3。当我点击另一个人时,表单本身不会更新。

我的代码

更新表单的更新组件:

const UpdateForm = ({ updatePerson, personToUpdate, handleInputChange }) => {

  let _name, _city, _age, _id;

  const submit = (e) => {
    e.preventDefault();

    updatePerson({
      name: _name.value,
      city: _city.value,
      age: _age.value,
      _id: _id.value
    });

  };

  return (
    <div>
      <form onSubmit={submit}>
        <h3>Update Person</h3>
        <label htmlFor="_id">Some Unique ID: </label>
        <input type="text" name="_id" ref={input => _id = input}  id="_id" defaultValue={personToUpdate._id} onChange={input => handleInputChange(personToUpdate)} required />
        <br />
        <label htmlFor="name">Name: </label>
        <input type="text" name="name" ref={input => _name = input} id="name" defaultValue={personToUpdate.name} onChange={input => handleInputChange(personToUpdate)} />
        <br />
        <label htmlFor="city">City: </label>
        <input type="text" name="city" ref={input => _city = input} id="city" defaultValue={personToUpdate.city} onChange={input => handleInputChange(personToUpdate)} />
        <br />
        <label htmlFor="age">Age: </label>
        <input type="text" name="age" ref={input => _age = input} id="age" defaultValue={personToUpdate.age} onChange={input => handleInputChange(personToUpdate)} />
        <br />
        <input type="submit" value="Submit" />
      </form>

    </div>
  );
};

export default UpdateForm;

人员组件的相关部分:

class Person extends Component {

  nameClick() {
    if (this.props.person._id !== this.props.personToUpdate._id) {
      this.props.setForUpdate(this.props.person);
      this.forceUpdate();
    }
    else {
      this.props.toggleUpdatePersonPanel();
    }

  }

    render() {
        return (
          <div>
            <span onClick={this.nameClick}>
                {this.props.person.name} ({this.props.person.age})
            </span>
          </div>
        );
    }
}

export default Person;

PeopleList 的相关部分,其中包含人员:

class PeopleList extends Component {

  render() {
    return(
      <div>
        {this.props.people.map((person) => {
          return <Person
            key={person._id}
            person={person}
            updatePersonPanel={this.props.updatePersonPanel}
            setForUpdate={this.props.setForUpdate}
            personToUpdate={this.props.personToUpdate}
            />;
        })}
      </div>
    );
  }

} // end class

export default PeopleList;

FormReducer,仅包含相关操作:

export default function formReducer(state = initialState.form, action) {
  let filteredPeople;

  switch (action.type) {
    case TOGGLE_UPDATE_PANEL:
      return Object.assign({}, state, { updatePersonPanel: false }, { personToUpdate: {
        _id: "",
        name: "",
        city: "",
        age: ""
      }});
    case SET_FOR_UPDATE:            
      return Object.assign({}, state, { personToUpdate: action.person }, { updatePersonPanel: true });
    case UPDATE_RECORD:
      filteredPeople = state.people.filter((person) => {
        return person._id === action.person._id ? false : true;
      }); // end filter

      return Object.assign({}, state, { people: [ ...filteredPeople, action.person] }, { personToUpdate: {
        _id: "",
        name: "",
        city: "",
        age: ""
      }}, { updatePersonPanel: false });
    case HANDLE_INPUT_CHANGE:
      return Object.assign({}, state, { personToUpdate: action.person });
    default:
      return state;
  }

}

我的初始状态文件的相关部分:

  form: {
    people: [
      {
        _id: "adfpnu64",
        name: "Johnny",
        city: "Bobville",
        age: 22
      },
      {
        _id: "adf2pnu6",
        name: "Renee",
        city: "Juro",
        age: 21
      },
      {
        _id: "ad3fpnu",
        name: "Lipstasch",
        city: "Bobville",
        age: 45
      }
    ],
    updatePersonPanel: false,
    personToUpdate: {
      _id: "",
      name: "",
      city: "",
      age: ""
    },
  }

尝试解决方案(到目前为止)

  • 我尝试通过将 form 属性切换为 value 而不是 defaultValue 来使该组件成为完全受控的组件。当我这样做时,名称切换得很好,但形式变得不可更改且无用。

我的问题

几乎所有此类问题的解决方案都建议使用 redux-form 或提供 two-way binding solutions that work fine in React without reduce我想知道如何使用 Redux 来做到这一点,而不使用 redux-form 或任何额外的东西(如果可能的话)。有没有办法在不触及生命周期方法的情况下解决这个问题?

结论(目前)

好吧,现在,我决定让我的表单不受控制,并使用一些经典的 Js DOM 方法和生命周期方法来控制表单。不管出于什么原因,一旦我采用了一些答案建议,我的浏览器就会耗尽我的 CPU 并崩溃,大概是因为存在某种无限循环。如果有人有进一步的建议,我将非常感激。现在我满足于此:

class UpdateForm extends Component {

  constructor(props){
    super(props);

    this.submit = this.submit.bind(this);
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.personToUpdate._id !== this.props.personToUpdate._id) {
      document.getElementById("name").value = nextProps.personToUpdate.name;
      document.getElementById("age").value = nextProps.personToUpdate.age;
      document.getElementById("city").value = nextProps.personToUpdate.city;
    }

  }

  submit(e) {
    e.preventDefault();

    this.props.updatePerson({
      name: document.getElementById("name").value,
      city: document.getElementById("city").value,
      age: document.getElementById("age").value,
      _id: this.props.personToUpdate._id
    });
  }

  render() {
    return (
      <div>
        <form onSubmit={this.submit}>
          <h3>Update Person</h3>
          Unique ID: {this.props.personToUpdate._id}
          <br />
          <label htmlFor="name">Name: </label>
          <input type="text" name="name" id="name" ref="name" defaultValue={this.props.personToUpdate.name} required />
          <br />
          <label htmlFor="city">City: </label>
          <input type="text" name="city" id="city" ref="city" defaultValue={this.props.personToUpdate.city} required />
          <br />
          <label htmlFor="age">Age: </label>
          <input type="text" name="age" id="age" ref="age" defaultValue={this.props.personToUpdate.age} required />
          <br />
          <input type="submit" value="Update" />
        </form>

      </div>
    );
  }
} // end class

export default UpdateForm;

我很快就会探索redux-form,因为很明显,将表单作为输入和输出是一件不稳定的事情。目前,我的小应用程序可以运行。

最佳答案

是的,有,而且您走在正确的道路上。方法是使用 value 而不是 defaultValue 但您必须从状态读取 value,然后使用 onChange 处理程序来修改状态。

类似的东西

this.state = {inputText:''}

然后在输入字段中

<input value={this.state.inputText} onChange={this.handleChange}/>

handleChange 函数将是

handleChange(event){
   this.setState({inputText:event.target.value})
}

请记住在构造函数中绑定(bind) handleChange 事件,以便您可以将其作为 this.handleChange 传递到输入字段的 onChange 属性中。

类似这样的事情

this.handleChange = this.handleChange.bind(this)

https://facebook.github.io/react/docs/forms.html - 这是有关它的官方文档

此外,如果您想在 redux 中执行此操作,则同样的逻辑适用于输入字段

<input value={this.props.inputText} onChange={this.props.handleChange}/>

其中 inputTexthandleChange 是分别通过 props 传递给组件的 redux 状态和操作

对于您的情况,我想它必须类似于您从 people 数组和绑定(bind)到 onChange< 的 action 中“读取”值。/code> 修改 statepeople 数组中的值。

<--编辑-->

对于这个例子,如何做到这一点。将 redux 状态下的 people 作为 people 属性传递给组件。将操作 changePeople(newPeople) 作为 prop 传递给组件,该组件接受参数 newPeople 并更改 redux 状态中的 people 以使其具有值newPeople。由于 people 嵌套在 form 中,因此您必须执行一些 Object.assign 等操作来修改状态。

现在,在使用 people 属性的组件中,使用 map 函数填充复选框。 map 函数采用第二个参数 index,因此对于每个复选框都有一个函数将本地状态变量 currentPerson 设置为 index 的值>索引

this.props.people.map((person,index) => 
    return <Checkbox onClick={()=>this.setState(currentPerson:index)}/>
) 

因此,每次您单击复选框时,currentPerson 都会指向相应的index

现在输入字段可以是

<input value={this.props.people[this.state.currentPerson].name} onChange={this.handleChange.bind(this,'name')}/>

这用于“名称”输入字段。它从 people 数组的 currentPerson 索引读取,该索引已作为 prop 向下传递。

这就是handleChange的样子

handleChange(property,event){
  const newPeople = [
                    ...this.props.people.slice(0, this.state.currentPerson),
                    Object.assign({}, this.props.people[this.state.currentPerson], {
                        [property]: event.target.value
                    }),
                    ...this.props.people.slice(this.state.currentPerson + 1)
                    ]

  this.props.changePeople(newPeople)

}

handleChange 采用一个属性(因此您不必为每个输入字段编写单独的处理程序)。 newPeople 基本上修改了从 props 传递的 people 中当前索引 this.state.currentPerson 处的元素(ES6此处使用的语法。如果您有疑问,请询问)。然后使用 changePeople 操作分派(dispatch)它,该操作也作为 props 传递。

关于javascript - 更新表单中的数据。保持可编辑状态。 (与 Redux react ,无 redux-form),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43621697/

相关文章:

javascript - 剪贴板事件

vb.net - 检查列表是否被修改

reactjs - 刷新页面时Cloudfront返回403禁止

javascript - php函数在表单内调用

javascript - 向电子邮件提交表格后,我收到 2 封电子邮件,而不是 1 封

javascript - 如何正确使用map函数的索引来访问数组中的元素

javascript - 如何在react-native和Redux中获取 Action 创建者的全局状态?

javascript - 如何在[javascript或jquery]字段中显示播放声音的名称(在按键上)?

javascript - 如果值是,则 Handlebars 助手必须返回值

javascript - 遍历数组但有时间延迟