在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 問答/C  HTML/ React 中通過數(shù)組渲染的組件怎么響應(yīng) state 的更新?

React 中通過數(shù)組渲染的組件怎么響應(yīng) state 的更新?

場景描述

我在做一個添加用戶信息的對話框,用戶可能又若干個電話,所以需要自由增刪電話輸入框。
如圖:

問題背景

我是在對話框組件的 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>&nbsp;
                        <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>
2017年9月20日 06:56