我有一份人员名单。我想:
一切正常,直到#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;
Person Component 的相关部分:
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;
Form Reducer ,仅提供相关操作:
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: ""
},
}
value
而不是defaultValue
来使组件成为完全受控的组件。当我这样做时,名称切换得很好,但形式变得无法改变和无用。几乎所有这类问题的解决方案都建议使用redux-form或者提供two-way binding solutions that work fine in React without reduce。 我想知道如何在不使用redux-form或其他任何额外内容的情况下使用Redux执行此操作。有没有办法在不触及生命周期方法的情况下解决此问题?
好吧,现在,我决定让我的表单不受控制,并使用一些经典的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
,因为很明显,作为输入和输出的表单是一个不稳定的业务。现在,我的小应用程序正常工作。
答案 0 :(得分:1)
是的,你正走在正确的道路上。方法是使用value
而不是defaultValue
,但您必须从状态读取value
,然后使用onChange
处理程序修改状态。
像
这样的东西this.state = {inputText:''}
然后在输入字段
<input value={this.state.inputText} onChange={this.handleChange}/>
handleChange
功能将是
handleChange(event){
this.setState({inputText:event.target.value})
}
请记住在构造函数中绑定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
是redux状态,并且操作分别通过props
传递给组件
对于你的情况,我想它必须像你在哪里阅读&#39;来自people
数组的值和action
绑定到onChange
的值会修改people
中state
数组中的值。
&LT; - 编辑 - &GT;
如何就此案件做到这一点。将redux状态的people
作为people
道具传递给组件。将操作changePeople(newPeople)
作为支柱传递给组件,该支柱接受参数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')}/>
这是针对&#39;名称&#39;输入字段。它从currentPerson
数组的people
索引读取,该数组已作为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
基本上修改了从this.state.currentPerson
传递的people
中当前索引props
的元素(此处使用的是ES6语法。如果您有疑问,请询问)。然后使用changePeople
动作调度它,该动作也作为道具传递。