How to map the value of 2 inputs in React?

Asked

Viewed 36 times

1

I’m creating a kind of Todolist in React and had the idea to use two inputs.

The code is divided into 3 components:

App.js:

import React, { useState } from "react";
import Form from "./Form";
import Modal from './Modal'

const App = () => {
  const [value, setValue] = useState("");
  const [value2,setValue2] = useState("")
  const [todos, setTodos] = useState([]);

  const getValue = (event)=>{
    setValue(event.target.value)
  }

  const getValue2=(event)=>{
    setValue2(event.target.value)
  }
  return (
    <div>
      <Form 
      valueProp={value} 
      valueProp2={value2}
      onChangeProp={getValue}
      onChangeProp2={getValue2}
      typeProp="submit"
      handleSubmitProp={(e)=>{
        e.preventDefault();
        setTodos([...todos, value]);
      }}/>
      <ul>
        {todos.map((todo, index) => (
          <li key={index}><Modal title={todo} content={value2}/></li>
        ))}
      </ul>
    </div>
  );
};

export default App;

Form.js:

import React from 'react'

export default function Form({valueProp,valueProp2,typeProp,onChangeProp,onChangeProp2,handleSubmitProp}){
  return(
    <>
    <form onSubmit = {handleSubmitProp}>
      <input value = {valueProp} onChange={onChangeProp}/>
      <input value = {valueProp2} onChange={onChangeProp2}/>
      <button type={typeProp}>ENTER</button>
    </form>
      
    </>
  )
}

Modal.js:

import React from 'react'

export default function Modal({title,content}){
  return(
    <>
      <p>{title}</p>
      <p>{content}</p>
    </>
  )
}

The problem with this application is that when the items (placed in the input) appear on the screen the following happens:

  • The estate title when rendered is unchangeable after Submit (which is what I want).

  • Already the property content, when rendered is not immutable, because when the input is moved again it changes, following the value of the second input.

To make it clearer I’ll put an image:

Essa é a situação da tela após o submit:

This is the situation of the screen after I give the Ubmit, apparently normal.

Essa é a situação da tela após eu alterar o input

This is the screen situation after I change the input value (without giving Ubmit again !), notice that the first value was unchanged but the second changed.

I believe the error is in the mapping part (line 30 of the App.js). Can someone help me solve this problem ? what I need to do to make the second value of the input unchanged after rendering ?

1 answer

0


The problem is in <Modal title={todo} content={value2}/>, it makes direct reference to the state of value2 in content={value2}, therefore any change in that state shall be reflected in Modal.

Looking at your question, it seems to me that your idea is that the first input is the title and the second being content. If that’s what I’m thinking, my tip is you create an object as follows:

{ title: value, content: value2 }

This would give a greater semantics, besides causing value2 is not re-notified directly on Modal, making the value immutable within this component.

In its status function for the todos would look this way:

setTodos([...todos, { title: value, content: value2 }])

Now it’s time to render the Modal would look this way:

{todos.map((todo, index) => (
  <li key={index}>
    <Modal title={todo.title} content={todo.content} />
  </li>
 ))}

Notice the logic for the Modal to render the title and the content:

title={todo.title} content={todo.content}

See the example below the code (adapted to run in the OS snippet):

function Form ({
  valueProp,
  valueProp2,
  typeProp,
  onChangeProp,
  onChangeProp2,
  handleSubmitProp
}) {
  return (
    <div>
      <form onSubmit={handleSubmitProp}>
        <input value={valueProp} onChange={onChangeProp} />
        <input value={valueProp2} onChange={onChangeProp2} />
        <button type={typeProp}>ENTER</button>
      </form>
    </div>
  )
}

function Modal ({ title, content }) {
  return (
    <div>
      <p>{title}</p>
      <p>{content}</p>
    </div>
  )
}

const App = () => {
  const [value, setValue] = React.useState('')
  const [value2, setValue2] = React.useState('')
  const [todos, setTodos] = React.useState([])

  const getValue = event => {
    setValue(event.target.value)
  }

  const getValue2 = event => {
    setValue2(event.target.value)
  }
  return (
    <div>
      <Form
        valueProp={value}
        valueProp2={value2}
        onChangeProp={getValue}
        onChangeProp2={getValue2}
        typeProp='submit'
        handleSubmitProp={e => {
          e.preventDefault()
          setTodos([...todos, { title: value, content: value2 }])
        }}
      />
      <ul>
        {todos.map((todo, index) => (
          <li key={index}>
            <Modal title={todo.title} content={todo.content} />
          </li>
        ))}
      </ul>
    </div>
  )
}

ReactDOM.render( < App / > , document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>


I had to replace <></> for <div></div> and use React.useState for the above example.

  • 1

    Thank you so much ! Your solution has helped too much !

Browser other questions tagged

You are not signed in. Login or sign up in order to post.