简体   繁体   中英

Splice removing the wrong index

so I'm trying to build a dynamic textfield, everything is working fine but I'm having a problem removing a data from state/array. splice is always removing the last index instead of a custom index. here's my whole code. I'm using reactjs as frontend framework by the way.

import React from 'react'

class Form extends React.Component {
    constructor(props){
        super(props)

        this.state = {
            firstName: "",
            lastName: "",
            books: []
        }

        this.onSubmitHandle = this.onSubmitHandle.bind(this)
        this.onChangeHandle = this.onChangeHandle.bind(this)
    }

    onSubmitHandle = (event) => {
        event.preventDefault()
        console.log(this.state)
    }

    onChangeHandle = (event) => {
        event.preventDefault()

        if(["book"].includes(event.target.name)) {
            let books = [...this.state.books]
            books[event.target.dataset.id][event.target.name] = event.target.value
        } else {
            this.setState({
                [event.target.name]: event.target.value
            })
        }
    }

    addNewRow = () => {
        this.setState((prevState) => ({
            books: [...prevState.books, { "book": "" }]
        }))
    }

    removeRow = (index) => {
    const newBooks = [...this.state.books];
    newBooks.splice(index, 1)
    this.setState({books: newBooks})
    }
     
    
    render() {
        return(
            <div>
                <form onSubmit={this.onSubmitHandle}>
                    <input type="text" name="firstName" onChange={this.onChangeHandle} placeholder="First Name" />
                    <input type="text" name="lastName" onChange={this.onChangeHandle} placeholder="Last Name" />
                    <br></br>
                    {
                        this.state.books.map((val, i) => {
                            return(
                                <div key={i}>
                                    <input type="text" data-id={i} onChange={this.onChangeHandle} name="book" placeholder={i} />
                                    <button type="button" onClick={this.removeRow.bind(this, i)}>Remove {i}</button>
                                </div>
                            )
                        })
                    }
                    <br></br>
                    <button type="button" onClick={this.addNewRow.bind(this)}>Add</button>
                    <br></br>
                    <button type="submit">Submit</button>
                </form>
            </div>
        )
    }
}

export default Form

The function itself and splice is working just fine. Your issue is with the react state update.

There are several issues with your code.

First, You bind the input element only in one way, so it would not be reactive if there is a state update. Furthermore, as its value is not bound to a variable, react does not see any issue with keeping it alive if the number of elements changes. You can read more about keys here: https://reactjs.org/docs/lists-and-keys.html

To fix the issue. set value={val.book} to the input element.

If you do the change suggested in step 1, you will find another issue with your code, that is you have an error in your onChangeHandle function. Basically, you do not update the state here as you simply update the value of an object. In general, I think it is advisable to avoid such assignments when working with react. Try using pure functions wherever possible. Anyway, try changing your change handler to the following:

onChangeHandle = (event) => {
  event.preventDefault()
  
  if(event.target.name === 'book') {
    let books = [...this.state.books]
    books[event.target.dataset.id][event.target.name] = event.target.value
    this.setState({
        books,
    })
    return;
  }

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

This will ensure that the state updates whenever you change the value of the input and that the value is correctly reflected in your input element.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM