Home > Blockchain >  How to reset state with event.target.value and make it persist on multiple <li>
How to reset state with event.target.value and make it persist on multiple <li>

Time:05-22

I am trying to grab the user input on key pressed and pass it to that list above next. I feel like there must be a way to reset the state and make it persist, but I just can't figure it out? How can I understand this?

import { useState, useEffect, useRef, useMemo } from 'react';
import '../sign.css';

const VALUES = [
  { id: 1, label: "name", text: "Hi, What is your Name?", placeholder: "Enter your full name" },
  { id: 2, label: "uname", text: "What shall we call you?", placeholder: "Enter a username" },
  { id: 3, label: "email", text: "Enter you email", placeholder: "Email" },
  { id: 4, label: "password", text: "Choose a password", placeholder: "make sure you dont forget" },
  { id: 5, label: "signup", text: "sign up", placeholder: ""},
];


export default function SignUp() {
  
  const [show, setShow] = useState(VALUES)
  const [currentIndex, setCurrentIndex] = useState(0);
  const [details, setDetails] = useState('');

  useEffect(() => {
    
  }, [show]);
  
  const onKeyPressed = (ev, id) => {
    if (ev.charCode === 13) {
      ev.preventDefault();
      const nextRender = currentIndex   1;
      if (nextRender < show.length) {
        setCurrentIndex(nextRender);
        setDetails(ev.target.value);
      } else {
        //todo
      }
    }
  }
  const displayItem = useMemo(() => show[currentIndex], [show, currentIndex]);
 
  return (
    <div className="container" id="container">
      <div className="navigation">
        <ol>
            <li><a href="#"  dataref="name">{this should display their name}</a></li>
            <li><a href="#"  dataref="uname">{this should display their username}</a></li>
            <li><a href="#"  dataref="email">{this should display their email}</a></li>
        </ol>
      </div>
      <form id="sign-form" className="sign-form">
        <ol className="questions">
          {
            <li onKeyPress={(KeyboardEvent) => onKeyPressed(KeyboardEvent, displayItem.id)} key={displayItem.id} >
              <span><label htmlFor={displayItem.label}>{displayItem.text}</label></span>
              <input id={displayItem.id} name={displayItem.label} type="text" placeholder={displayItem.placeholder} autoFocus/>
            </li>
          };  
        </ol>
     </form>
    </div>
  )

CodePudding user response:

I let you the code that it works like I think that you want

import { useState, useEffect, useRef, useMemo } from 'react';

const VALUES = [
  { id: 1, label: "name", text: "Hi, What is your Name?", placeholder: "Enter your full name" },
  { id: 2, label: "uname", text: "What shall we call you?", placeholder: "Enter a username" },
  { id: 3, label: "email", text: "Enter you email", placeholder: "Email" },
  { id: 4, label: "password", text: "Choose a password", placeholder: "make sure you dont forget" },
  { id: 5, label: "signup", text: "sign up", placeholder: ""},
];


export default function SignUp() {

  const [show, setShow] = useState(VALUES)
  const [currentIndex, setCurrentIndex] = useState(0);
  const [details, setDetails] = useState({});

  useEffect(() => {

  }, [show]);

  const onKeyPressed = ( ev, id ) => {
    if (ev.charCode === 13) {
      ev.preventDefault();
      const nextRender = currentIndex   1;
      if (nextRender < show.length) {
        setCurrentIndex(nextRender);
        const label = VALUES[currentIndex].label;
        details[label] = ev.target.value;
        setDetails(details);
      } else {
        //todo
      }
    }
  }
  const displayItem = useMemo(() => show[currentIndex], [show, currentIndex]);

  return (
    <div className="container" id="container">
      <div className="navigation">
        <ol>
          {Object.keys(details).map((key) => (
            <li><a href="#" dataref={key}>{key}: {details[key]}</a></li>
          ))}
        </ol>
      </div>
      <form id="sign-form" className="sign-form">
        <ol className="questions">
          <li onKeyPress={( KeyboardEvent ) => onKeyPressed(KeyboardEvent, displayItem.id)} key={displayItem.id}>
            <span><label htmlFor={displayItem.label}>{displayItem.text}</label></span>
            <input id={displayItem.id} name={displayItem.label} type="text" placeholder={displayItem.placeholder}
                   autoFocus/>
          </li>
        </ol>
      </form>
    </div>
  )
}

CodePudding user response:

Right, I think I know what you mean now. I've run the code in CodeSandbox and it makes sense. You want to do like a stepper for your registration where you ask a single question at a time.

Storing values in an object would still be a preferable way of doing this. But you need to get the label for the value and append it to the existing object. You can build your object with data when you go through your stepper.

Here is a working solution. Hopefully that's what you were looking for: https://codesandbox.io/s/unruffled-pasteur-76xux4?file=/src/App.js

I modified the onKeyPressed to grab the label from VALUES array based on the index we are currently on. Then that label is used as a key inside of the object where the value is the value from the event handler

 const onKeyPressed = (ev, id) => {
    if (ev.charCode === 13) {
      ev.preventDefault();
      const label = show[currentIndex].label; // grab the label based on the current index
      const nextRender = currentIndex   1;
      if (nextRender < show.length) {
        setCurrentIndex(nextRender);
        setDetails({ ...details, [label]: ev.target.value }); // add the value to the details object where key is the label
      } else {
        //todo
      }
    }
  };
  • Related