連絡先オブジェクトを状態として保存するコンポーネントがあります-{firstName: "John"、lastName: "Doe"、phone: "1234567890}このオブジェクトを編集するフォームを作成しますが、入力に値を保持する場合元の接触パラメーターの場合、各入力を制御コンポーネントにする必要がありますが、状態が{contact:{...}}のみを保持するため、各パラメーターに調整するhandleChange関数を作成する方法がわかりません。以下は私が現在持っているものです-
getInitialState: function () {
return ({contact: {}});
},
handleChange: function (event) {
this.setState({contact: event.target.value });
},
render: function () {
return (
<div>
<input type="text" onChange={this.handleChange} value={this.state.contact.firstName}/>
<input type="text" onChange={this.handleChange} value={this.state.contact.lastName}/>
<input type="text" onChange={this.handleChange} value={this.state.contact.lastName}/>
</div>
);
}
私は私のハンドルを変えたい
handleChange: function (event) {
this.setState({contact.firstName: event.target.value });
}
これを行うための「単純な」方法と「スマートな」方法があります。あなたが私に尋ねるなら、物事をスマートな方法で行うことは必ずしも最善ではありません。この場合、両方とも非常に理解しやすいものです。
サイドノート:考えてほしいことの1つは、contact
オブジェクトを更新する必要があるか、またはfirstName
などを直接状態のままにしておくことができるかということです。コンポーネントの状態のデータがたくさんあるのでしょうか?その場合は、責任をより狭くして、より小さなコンポーネントに分割することをお勧めします。
changeFirstName: function (event) {
const contact = this.state.contact;
contact.firstName = event.target.value;
this.setState({ contact: contact });
},
changeLastName: function (event) {
const contact = this.state.contact;
contact.lastName = event.target.value;
this.setState({ contact: contact });
},
changePhone: function (event) {
const contact = this.state.contact;
contact.phone = event.target.value;
this.setState({ contact: contact });
},
render: function () {
return (
<div>
<input type="text" onChange={this.changeFirstName.bind(this)} value={this.state.contact.firstName}/>
<input type="text" onChange={this.changeLastName.bind(this)} value={this.state.contact.lastName}/>
<input type="text" onChange={this.changePhone.bind(this)} value={this.state.contact.phone}/>
</div>
);
}
handleChange: function (propertyName, event) {
const contact = this.state.contact;
contact[propertyName] = event.target.value;
this.setState({ contact: contact });
},
render: function () {
return (
<div>
<input type="text" onChange={this.handleChange.bind(this, 'firstName')} value={this.state.contact.firstName}/>
<input type="text" onChange={this.handleChange.bind(this, 'lastName')} value={this.state.contact.lastName}/>
<input type="text" onChange={this.handleChange.bind(this, 'phone')} value={this.state.contact.lastName}/>
</div>
);
}
このセクションには、上記と同じ例が含まれていますが、ES2015 +の機能を使用しています。
ブラウザ間で次の機能をサポートするには、 Babel を使用してコードを変換する必要があります。プリセット es2015 および react 、およびプラグイン stage- 。
以下に更新された例を示します。 object destructuring を使用して状態から連絡先を取得し、 spread operator を使用して、既存のオブジェクトを変更する代わりに更新された連絡先オブジェクトを作成し、コンポーネントを作成します- クラスReact.Component を拡張し、 矢印関数 を使用してコールバックを作成することで、bind(this)
が不要になります。
class ContactEdit extends React.Component {
changeFirstName = (event) => {
const { contact } = this.state;
const newContact = {
...contact,
firstName: event.target.value
};
this.setState({ contact: newContact });
}
changeLastName = (event) => {
const { contact } = this.state;
const newContact = {
...contact,
lastName: event.target.value
};
this.setState({ contact: newContact });
}
changePhone = (event) => {
const { contact } = this.state;
const newContact = {
...contact,
phone: event.target.value
};
this.setState({ contact: newContact });
}
render() {
return (
<div>
<input type="text" onChange={this.changeFirstName} value={this.state.contact.firstName}/>
<input type="text" onChange={this.changeLastName} value={this.state.contact.lastName}/>
<input type="text" onChange={this.changePhone} value={this.state.contact.phone}/>
</div>
);
}
}
handleChangeFor
は カリー化された関数 であることに注意してください。propertyName
で呼び出すと、コールバック関数が作成され、呼び出されると、状態の(新しい)連絡先オブジェクトの[propertyName]
が更新されます。
class ContactEdit extends React.Component {
handleChangeFor = (propertyName) => (event) => {
const { contact } = this.state;
const newContact = {
...contact,
[propertyName]: event.target.value
};
this.setState({ contact: newContact });
}
render() {
return (
<div>
<input type="text" onChange={this.handleChangeFor('firstName')} value={this.state.contact.firstName}/>
<input type="text" onChange={this.handleChangeFor('lastName')} value={this.state.contact.lastName}/>
<input type="text" onChange={this.handleChangeFor('phone')} value={this.state.contact.lastName}/>
</div>
);
}
}
ES6ワンライナーアプローチ
<input type="text"
value={this.state.username}
onChange={(e) => this.setState({ username: e.target.value })}
id="username"/>
ネストされたオブジェクトの状態を更新するには、2つの方法があります。
これがどのように機能するかを見ることができます JS Fiddle 。コードは次のとおりです。
var Component = React.createClass({
getInitialState: function () {
return ({contact: {firstName: "first", lastName: "last", phone: "1244125"}});
},
handleChange: function (key,event) {
console.log(key,event.target.value);
//way 1
//var updatedContact = JSON.parse(JSON.stringify(this.state.contact));
//updatedContact[key] = event.target.value;
//way 2 (Recommended)
var updatedContact = React.addons.update(this.state.contact, {
[key] : {$set: event.target.value}
});
this.setState({contact: updatedContact});
},
render: function () {
return (
<div>
<input type="text" onChange={this.handleChange.bind(this,"firstName")} value={this.state.contact.firstName}/>
<input type="text" onChange={this.handleChange.bind(this,"lastName")} value={this.state.contact.lastName}/>
<input type="text" onChange={this.handleChange.bind(this,"phone")} value={this.state.contact.phone}/>
</div>
);
}
});
ReactDOM.render(
<Component />,
document.getElementById('container')
);
これが一般的なものです。
handleChange = (input) => (event) => {
this.setState({
...this.state,
[input]: event.target.value
});
}
そして、このように使用します。
<input handleChange ={this.handleChange("phone")} value={this.state.phone}/>
最も近いアプローチ
以下は、単純なアプリケーションで使用したアプローチです。これは React で推奨されるアプローチであり、本当にすっきりしています。 ArneHugoの答えに非常に近く、私もhmに感謝します。アイデアは、そのフォームとリアクションフォームサイトを組み合わせたものです。各フォーム入力のname属性を使用して、特定のpropertyNameを取得し、それに基づいて状態を更新できます。これは、上記の例のES6での私のコードです。
class ContactEdit extends React.Component {
handleChangeFor = (event) => {
const name = event.target.name;
const value = event.target.value;
const { contact } = this.state;
const newContact = {
...contact,
[name]: value
};
this.setState({ contact: newContact });
}
render() {
return (
<div>
<input type="text" name="firstName" onChange={this.handleChangeFor} />
<input type="text" name="lastName" onChange={this.handleChangeFor}/>
<input type="text" name="phone" onChange={this.handleChangeFor}/>
</div>
);
}
}
違い:
ここではコードが少なく、フォームから任意の種類の入力を取得するスマートな方法があります。name属性には入力ごとに一意の値があるためです。作業中の 例 を参照してください。初期段階の実験的なブログアプリケーション用にCodPenにあります。
<input>
要素には多くの場合、nameというプロパティがあります。イベントハンドラーから受け取るイベントオブジェクトからこの名前プロパティにアクセスできます。
一般化された変更ハンドラを書く
constructor () {
super();
this.state = {
name: '',
age: ''
};
this.handleChange = this.handleChange.bind(this);
}
handleChange (evt) {
this.setState({ [evt.target.name]: evt.target.value });
}
render () {
return (
<form>
<label>Name</label>
<input type="text" name="name" onChange={this.handleChange} />
<label>Age</label>
<input type="text" name="age" onChange={this.handleChange} />
</form>
);
}
handleChange(event){
this.setState({[event.target.name]:event.target.value});
this.setState({[event.target.name]:event.target.value});
}