【问题标题】:React - handle change of input with state rendered by iteration through an arrayReact - 使用通过数组迭代呈现的状态来处理输入的变化
【发布时间】:2017-08-21 07:35:57
【问题描述】:

这是我的代码...

    class Module extends Component {
        constructor() {
            super()

            this.state = {
                inputs: [
                    { type: 'text', placeholder: 'placeholder text', name: 'text1', id: 'text1', value: 'aaa' },
                    { type: 'text', placeholder: 'another placeholder text', name: 'text2', id: 'text2', value: '' },
                    { type: 'text', placeholder: 'third placeholder text', name: 'text3', id: 'text3', value: '' },
                ]
            }

            this.handleInputChange = this.handleInputChange.bind(this)
            this.saveModule = this.saveModule.bind(this)
        }

        handleInputChange(event) {
            this.setState ({
                [event.target.name]: event.target.value
            })
        }

        renderInput = (input) => {
            return(
                <div key={ input.id }>
                    <input
                        type={ input.type }
                        name={ input.name }
                        placeholder={ input.placeholder }
                        onBlur={ this.saveModule }
                        value={ input.value }
                        onChange={ this.handleInputChange }
                    />
                </div>
            )
        }

        render() {
            return (
                <div>
                    { this.state.inputs.map(this.renderInput) }
                </div>
            )
        }
    }

    export default Module

如何处理以这种方式从状态呈现值的输入变化?! 如果我有 {this.state.input.value} 它工作得非常好,一旦我像这样重构它,setState 似乎不再达到它了。

有什么想法吗? :)

提前非常感谢!

【问题讨论】:

  • 首先您必须找到您将处理的对象的索引。所以考虑event.target.name作为过滤数组的条件。然后使用更改创建一个新数组。并设置状态。这是一个很好的方法stackoverflow.com/a/36010124/7744070

标签: javascript reactjs


【解决方案1】:

由于您想直接在创建input 元素的input array 中进行更改,因此您需要在onChange 方法中进行更改。使用任何唯一属性(如名称或索引)来识别哪个元素已更改,迭代input array 找到该输入元素,然后更新该元素的值。更新输入数组中的值后,也更新状态输入数组,当react重新渲染组件时,值会自动反映在UI中。

检查工作代码:

class Module extends React.Component {
        constructor() {
            super()

            this.state = {
                inputs: [
                    { type: 'text', placeholder: 'placeholder text', name: 'text1', id: 'text1', value: 'aaa' },
                    { type: 'text', placeholder: 'another placeholder text', name: 'text2', id: 'text2', value: '' },
                    { type: 'text', placeholder: 'third placeholder text', name: 'text3', id: 'text3', value: '' },
                ]
            }

            this.handleInputChange = this.handleInputChange.bind(this)
        }

        handleInputChange(event) {
            let inputs = this.state.inputs.slice();
            for(let i in inputs){
                if(inputs[i].name == event.target.name){
                    inputs[i].value = event.target.value;
                    this.setState ({inputs});
                    break;
                }
            }
        }

        renderInput = (input, i) => {
            return(
                <div key={ input.id }>
                    <input
                        type={ input.type }
                        name={ input.name }
                        placeholder={ input.placeholder }
                        onBlur={ this.saveModule }
                        value={ input.value }
                        onChange={ this.handleInputChange }
                    />
                </div>
            )
        }

        render() {
            return (
                <div>
                    { this.state.inputs.map(this.renderInput) }
                </div>
            )
        }
    }


ReactDOM.render(<Module/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id='app'/>

【讨论】:

  • 你能解释一下你做了什么吗?用更多代码替换一堆代码对可能正在学习 React 的任何人都没有帮助
  • @DarrenSweeney 用正确的信息更新了答案。
  • 这很神奇,非常感谢您的解释,很有意义! :)
  • this.setState ({inputs}); 在一天结束时,您正在更新所有输入的状态。可以吗??
  • 肯定有比遍历整个数组更好的方法吗?你不能将元素传递给句柄函数吗?
【解决方案2】:

你必须先创建一个新状态来设置状态。

由于this.state 是不可变的,因此只需使用spread operatorObject.assign 修改旧状态即可创建新状态。

This video 是如何以不可变方式更改 javascript 对象的一个​​很好的参考。还有一个专门用于高效创建和修改不可变对象的库,名为immutable.js

Refer to this how to use immutable.js with react setState

(此代码经过测试)

class Module extends Component {
    constructor() {
        super()

        this.state = {
            inputs: [
                { type: 'text', placeholder: 'placeholder text', name: 'text1', id: 'text1', value: 'aaa' },
                { type: 'text', placeholder: 'another placeholder text', name: 'text2', id: 'text2', value: '' },
                { type: 'text', placeholder: 'third placeholder text', name: 'text3', id: 'text3', value: '' },
            ]
        }

        this.handleInputChange = this.handleInputChange.bind(this)
        this.saveModule = this.saveModule.bind(this)
    }

    // change this to an arrow function
    handleInputChange = (event) =>  {
        const name = event.target.name;
        const value = event.target.value;
        const oldInputState = this.state.inputs.find(i => i.name === name);
        // use the spread operator or Object.assign to create a brand new state object
        this.setState({
            ...,
            this.state, // copy everything from the old state
            // expect change the `inputs` value
            {inputs: [ // create a brand new array
                ...this.state.inputs.filter(i => i.name !== name),
                {...oldInputState, value} // replace old value with the new value
                // refer to that video I included, it's a great explanation
            ]}
        });
    }

    renderInput = (input) => {
        return(
            <div key={ input.id }>
                <input
                    type={ input.type }
                    name={ input.name }
                    placeholder={ input.placeholder }
                    onBlur={ this.saveModule }
                    value={ input.value }
                    onChange={ this.handleInputChange }
                />
            </div>
        )
    }

    render() {
        return (
            <div>
                { this.state.inputs.map(this.renderInput) }
            </div>
        )
    }
}

export default Module

祝你好运!

【讨论】:

  • 我认为,使用箭头函数和handleInputChange 不是必需的,他已经在构造函数中定义了绑定。
猜你喜欢
  • 2017-08-24
  • 2019-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-14
  • 2020-02-25
  • 1970-01-01
  • 2023-03-17
相关资源
最近更新 更多