我在做一個添加用戶信息的對話框,用戶可能又若干個電話,所以需要自由增刪電話輸入框。
如圖:
我是在對話框組件的 state 中維護(hù)一個數(shù)組 telsInput,來存儲電話輸入框數(shù)組。
在 render 函數(shù)中直接渲染這個數(shù)組 {this.state.telsInput}
當(dāng)點擊添加電話按鈕時,觸發(fā)事件,push 一個輸入框組件進(jìn)該數(shù)組。點擊刪除按鈕時,pop 出末尾的輸入框。
這樣就能滿足不同數(shù)量的電話需求。
我想把電話輸入框的值和 state 中的值綁定起來(可控組件),但通過數(shù)組渲染的輸入框組件的 value 不能響應(yīng) state 的變化。
我猜測問題出在下面的代碼中
/**
* 點擊’添加電話‘按鈕時觸發(fā),向 state.telsInput 中 push 一個 電話輸入框組件
**/
addTels = () => {
// telsInput 數(shù)組用于存儲電話輸入框組件
let telsInput = this.state.telsInput,
number = telsInput.length + 2;
const tel = <Input
placeholder={"電話" + number}
size="large"
key={number}
ref={(node) => this['userTels' + number] = node}
prefix={<Icon type="phone" />}
// 在 onChange 事件中獲取該輸入框的值來更新 state.userTels 對應(yīng)的值
onChange={(e) => { this.onChange(e, 'tel', number - 1) }}
// 我覺得問題出在這里
value={this.state.userTels[number - 1]}
style={{ marginTop: '10px' }}
/>;
telsInput.push(tel);
this.setState({
telsInput: telsInput,
removeable: true,
})
}
上面代碼中組件的 value 屬性設(shè)置為 {this.state.userTels[number - 1],我感覺這在編譯時,這里的 {this.state.userTels[number - 1]} 會直接被替換成對應(yīng)的字符串。由于初始值為空,所以在 render 函數(shù)中直接變?yōu)榱耍瑅alue='',所以才導(dǎo)致無法響應(yīng) state 中變化。
請問有什么辦法可以解決這種情況嗎,或者針對這種需求有其他的設(shè)計思路嗎?
import React from 'react';
import { Button, Modal, Input, Icon } from 'antd';
class UserDia extends React.Component {
constructor(props) {
super(props);
this.state = {
modalContain: '',
visible: false,
confirmLoading: false,
userName: props.uname || '',
userAddr: props.uaddress || '',
userTels: [],
telsInput: [],
removeable: false,
};
}
componentWillReceiveProps(nextProps) {
this.setState({
visible: nextProps.visible
})
}
addTels = () => {
let telsInput = this.state.telsInput,
number = telsInput.length + 2;
const tel = <Input
placeholder={"電話" + number}
size="large"
key={number}
ref={(node) => this['userTels' + number] = node}
prefix={<Icon type="phone" />}
onChange={(e) => { this.onChange(e, 'tel', number - 1) }}
value={this.state.userTels[number - 1]}
style={{ marginTop: '10px' }}
/>;
telsInput.push(tel);
this.setState({
telsInput: telsInput,
removeable: true,
})
}
removeTel = () => {
let telsInput = this.state.telsInput,
removeable = telsInput.length === 1 ? false : true;
telsInput.pop();
this.setState({
telsInput: telsInput,
removeable: removeable
});
}
showModal = () => {
this.setState({
visible: true,
});
}
handleOk = () => {
this.setState({
confirmLoading: true,
});
setTimeout(() => {
this.setState({
visible: false,
confirmLoading: false,
});
}, 2000);
}
handleCancel = () => {
this.setState({
visible: false,
});
}
onChange = (e, type, index) => {
switch (type) {
case 'name':
this.setState({ userName: e.target.value });
break;
case 'addr':
this.setState({ userAddr: e.target.value });
break;
case 'tel':
const userTels = this.state.userTels;
userTels[index] = e.target.value;
this.setState({ userTels: userTels})
}
}
emitEmpty = (type) => {
switch (type) {
case 'name':
this.userNameInput.focus();
this.setState({ userName: '' });
break;
case 'addr':
this.userAddr.focus();
this.setState({ userAddr: '' })
break;
case 'tel':
break;
}
}
render() {
console.log(this.state.userTels);
let arr = [<Button>xx</Button>, <Button>ss</Button>]
const { visible, confirmLoading, modalContain, removeable, userName, userAddr, userTels, telsInput } = this.state,
nameSuffix = userName ? <Icon type="close-circle" onClick={() => {this.emitEmpty('name')}} /> : null,
addrSuffix= userAddr? <Icon type="close-circle" onClick={() => {this.emitEmpty('addr')}} /> : null;
return (
<Modal title="添加用戶"
maskClosable={false}
visible={visible}
onOk={this.handleOk}
confirmLoading={confirmLoading}
onCancel={this.handleCancel}
>
<div>
<Input
placeholder="用戶名"
size="large"
value={userName}
suffix={nameSuffix}
prefix={<Icon type="user" />}
ref={(node) => {this.userNameInput = node}}
onChange={(e) => { this.onChange(e, 'name') }}
style={{ marginBottom: '10px' }}
/>
<Input
placeholder="地址"
size="large"
value={userAddr}
suffix={addrSuffix}
prefix={<Icon type="home" />}
ref={(node) => {this.userAddr = node}}
onChange={(e) => { this.onChange(e, 'addr') }}
style={{ marginBottom: '10px' }}
/>
<Input
placeholder="電話1"
size="large"
value={userTels[0]}
prefix={<Icon type="phone" />}
onChange={(e) => { this.onChange(e, 'tel', 0) }}
/>
<span>
{telsInput}
</span>
<div style={{ marginTop: '10px', textAlign: 'center', fontSize: '14px', color: '#999' }}>
<Button type='primary' icon='plus-circle' onClick={this.addTels}>添加電話</Button>
<Button disabled={!removeable} icon='minus-circle-o' onClick={this.removeTel}>移除電話</Button>
</div>
</div>
</Modal>
)
}
}
export default UserDia;不要把jsx存到state里,而是應(yīng)該把數(shù)據(jù)存到state里,類似:
state= {
userTels:[]
}
addTels = () => {
this.setState({
telsInput: [...this.state.userTels, ''],
removeable: true,
})
}
在render函數(shù)里:
<span>
{
this.state.userTels.map((item, number) => {
return (
<Input
placeholder={"電話" + number}
size="large"
key={number}
ref={(node) => this['userTels' + number] = node}
prefix={<Icon type="phone" />}
onChange={(e) => { this.onChange(e, 'tel', number - 1) }}
value={item}
style={{ marginTop: '10px' }}
/>
)
})
}
</span>北大青鳥APTECH成立于1999年。依托北京大學(xué)優(yōu)質(zhì)雄厚的教育資源和背景,秉承“教育改變生活”的發(fā)展理念,致力于培養(yǎng)中國IT技能型緊缺人才,是大數(shù)據(jù)專業(yè)的國家
達(dá)內(nèi)教育集團(tuán)成立于2002年,是一家由留學(xué)海歸創(chuàng)辦的高端職業(yè)教育培訓(xùn)機(jī)構(gòu),是中國一站式人才培養(yǎng)平臺、一站式人才輸送平臺。2014年4月3日在美國成功上市,融資1
北大課工場是北京大學(xué)校辦產(chǎn)業(yè)為響應(yīng)國家深化產(chǎn)教融合/校企合作的政策,積極推進(jìn)“中國制造2025”,實現(xiàn)中華民族偉大復(fù)興的升級產(chǎn)業(yè)鏈。利用北京大學(xué)優(yōu)質(zhì)教育資源及背
博為峰,中國職業(yè)人才培訓(xùn)領(lǐng)域的先行者
曾工作于聯(lián)想擔(dān)任系統(tǒng)開發(fā)工程師,曾在博彥科技股份有限公司擔(dān)任項目經(jīng)理從事移動互聯(lián)網(wǎng)管理及研發(fā)工作,曾創(chuàng)辦藍(lán)懿科技有限責(zé)任公司從事總經(jīng)理職務(wù)負(fù)責(zé)iOS教學(xué)及管理工作。
浪潮集團(tuán)項目經(jīng)理。精通Java與.NET 技術(shù), 熟練的跨平臺面向?qū)ο箝_發(fā)經(jīng)驗,技術(shù)功底深厚。 授課風(fēng)格 授課風(fēng)格清新自然、條理清晰、主次分明、重點難點突出、引人入勝。
精通HTML5和CSS3;Javascript及主流js庫,具有快速界面開發(fā)的能力,對瀏覽器兼容性、前端性能優(yōu)化等有深入理解。精通網(wǎng)頁制作和網(wǎng)頁游戲開發(fā)。
具有10 年的Java 企業(yè)應(yīng)用開發(fā)經(jīng)驗。曾經(jīng)歷任德國Software AG 技術(shù)顧問,美國Dachieve 系統(tǒng)架構(gòu)師,美國AngelEngineers Inc. 系統(tǒng)架構(gòu)師。