问题
我有一份人员名单。我想要:
- 点击姓名选择要编辑的用户。
- 编辑该用户的信息,以便我可以点击提交按钮并更新列表。
- 如果我点击其他姓名,我想切换到该人的信息,而无需先特意关闭表单。
一切正常,直到#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}/>
其中 inputText
和 handleChange
是分别通过 props
传递给组件的 redux 状态和操作
对于您的情况,我想它必须类似于您从 people
数组和绑定(bind)到 onChange< 的
action
中“读取”值。/code> 修改 state
中 people
数组中的值。
<--编辑-->
对于这个例子,如何做到这一点。将 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/