1

I know how to create a list of names using one input text field. How do I create a list of people with an input field of first name and an input field of last name. Thus, how do you create a list of people using multiple input values which consist of last name and first name. How do I do this in react.js?

  • John Carter
  • Adam West
  • Mark Hamill
  • Stan Lee
  • Peter Parker
  • Clark Kent

Right now, I only now how to create a list like the following using only one input field:

  • John
  • Adam
  • Mark
  • Stan
  • Peter
  • Clark

The dots before each name is not necessary at this point.

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

function PostButton(props){
    var style = {
        width:24,
        height:24
    }
    return (
        <button style = {style} onClick = { () => props.handleClick()}>{props.label}</button>
    )
}
function PostText(props){
    var style = {
        border:"1px solid black",
        width: props.width
    }
    return (
        <div style = {style}>{props.text}</div>
    )
}
function Post(props){
    var style = {
        display:"flex"
    }
    return (
        <div style = {style}>
            <PostButton label = "x" handleClick = {props.removeItem}/>
            <PostTextFirstName text = {props.firstName} width = "200"/>
            <PostTextLastName text = {props.lastName} width = "200" />
        </div>
    )
}

function PostList(props){
    return (
        <ol>
        {
            props.postList.map((item,index) => 
                <Post key = {index} 
                      firstName = {item.firstName} 
                      lastName = {item.lastName}
                      removeItem = {() => props.removeItem(index)}
                />
             )
         }
        </ol>
    )  
}

class App extends React.Component{
    constructor(props){
        super(props)
        this.state = {value:"", items : []}
    } 
    handleChange(event){
        this.setState({value:event.target.value})
        console.log(this.state.value)
    }
    addItem()
    {
        var itemsCopy = this.state.items.slice()
        var truncatedString = this.state.value.substring(0,20);
        itemsCopy.push({"firstName":truncatedString})
        this.setState({items:itemsCopy,value:""})
    }
    removeItem(index)
    {
        var itemsCopy = this.state.items.slice()
        itemsCopy.splice(index,1);
    
        this.setState({items:itemsCopy})
    }
    render(){
        return (
            <div>
                <div>First Name</div>
                <input value = {this.state.value} onChange = {this.handleChange.bind(this)}/>
                <div>Last Name</div>
                <input value = {this.state.value} onChange = {this.handleChange.bind(this)}/>
                <button onClick = { () => this.addItem()}>Submit</button>
                <PostList postList = {this.state.items} 
                          removeItem = {this.removeItem.bind(this)}
                />
            </div>
        )
    }
}

ReactDOM.render(
    <App/>,
    document.getElementById("root")
)
user3501508
  • 153
  • 1
  • 6
  • Not sure I understand your question. Do you want to create a list of persons (first name + last name) based on successive submits of your form, or do you want to be able to append new pairs of first name / last name input fields to your form? – Thomas Hennes Jan 09 '18 at 06:39
  • I added more details to the question. I know how to add the first name via a single input field and build up a list of first names. How do I build up a list of people with their first name and last name using an input field of first name and input field of last name. I only know how to use one input field. I don't know how to do it with two input fields. I need to build a list of people with their first and last names, not just their first name. – user3501508 Jan 09 '18 at 06:42
  • One simple search: https://stackoverflow.com/questions/35965275/how-do-i-edit-multiple-input-controlled-components-in-react – Felix Jan 09 '18 at 07:05

1 Answers1

1

You have the general principle down right, your big mistake here is to handle two separate text fields with one single state variable. Obviously, when you do that, you will overwrite the first name when setting the last name and vice-versa.

Here are the changes you need to make:

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      firstname: "",
      lastname: "",
      items: []
    };
  }

  handleChange(event) {
    if (event.target.name === "firstname") {
      this.setState({ firstname: event.target.value });
    } else if (event.target.name === "lastname") {
      this.setState({ lastname: event.target.value });
    }
  }

  addItem() {
    this.setState({
      items: [ 
        ...this.state.items, 
        {
          firstName: this.state.firstname,
          lastName: this.state.lastname
        }
      ],
      firstname: "",
      lastname: ""
    });
  }

  removeItem(index) {
    const items = this.state.items.filter((e, idx) => idx !== index); 
    this.setState({ items });
  }

  render() {
    return (
      <div>
        <div>First Name</div>
        <input
          name="firstname"
          value={this.state.firstname}
          onChange={this.handleChange.bind(this)} />
        <div>Last Name</div>
        <input
          name="lastname"
          value={this.state.lastname}
          onChange={this.handleChange.bind(this)} />
        <button onClick={() => this.addItem()}>Submit</button>
        <PostList
          postList={this.state.items}
          removeItem={this.removeItem.bind(this)} />
      </div>
    );
  }
}

Note that I use the name attribute of each input to decide which corresponding variable to change in the state. Another possibility would have been to create 2 different functions, one to handle the firstName text changes, the other to handle the lastName text changes.

I've also simplified your addItem and removeItem methods, using a bit of ES6 syntax.

As you can see, the approach is the same one you had, save for the separate handling of first name and last name.

Here is a CodeSandbox with all pieces put together.

Thomas Hennes
  • 9,023
  • 3
  • 27
  • 36
  • Just wondering why my previous functions like PostButton were converted to const. – user3501508 Jan 11 '18 at 07:06
  • What is the difference between import ReactDOM from 'react-dom'; vs import { render } from 'react-dom'; – user3501508 Jan 11 '18 at 07:07
  • The conversion of PostButton from a function to a const assigned an 'arrow' function is just using ES6 syntax, but there's no real difference in behavior. There's also no difference between `import ReactDOM from 'react-dom';` and then using `ReactDOM.render();` and `import { render } from 'react-dom';` and then using `render();`. In one case we import an entire module and then used a named method from that module, in the other we directly import the named method, but the end result is strictly identical. – Thomas Hennes Jan 11 '18 at 09:17