Displaying an array value instead of a new value list in a React component

Situation -

Initial number input in text field - 1

List of Items -

  • 1
  • 6
  • 11

Upon removing 1 from the text field, the list becomes -

New List Items -

  • NaN
  • NaN
  • NaN

Now, if you input 4 in the field.

The updated List Items are -

  • NaN
  • NaN
  • 4
  • 9
  • 14

Expected Outcome -

The List should only show - 4, 9 and 14, not NaN, NaN, 4, 9, 14.

Please advise on what might be incorrect here.

Code Section -

import React, { useState } from "react";
import List from "./List";

const ReRendering = () => {
  const [number, setNumber] = useState(1);

  const getList = () => [number, number + 5, number + 10];

  return (
    <div>
      <input
        type="number"
        value={number}
        onChange={(e) => setNumber(parseInt(e.target.value, 10))}
      />
      <div>
        <List getList={getList} />
      </div>
    </div>
  );
};

export default ReRendering;

List.js File

import { useEffect, useState } from "react";

const List = ({ getList }) => {
  const [item, setItem] = useState([]);

  useEffect(() => {
    setItem(getList());
  }, [getList]);
  return (
    <div className="list">
      {item.map((x) => (
        <div key={x}>{x}</div>
      ))}
    </div>
  );
};

export default List;

Live Demo - https://codesandbox.io/s/gallant-gagarin-l18ni1?file=/src/ReRendering.js:0-463

Answer №1

When

setNumber(parseInt(e.target.value, 10))
is used, the number state will be set to NaN if the input field is empty because an empty string cannot be converted to an integer using parseInt.

console.log(parseInt(''));

Having NaN as a value can lead to issues as mentioned in the React warning:

Warning: Encountered two children with the same key, NaN. Keys should be unique to ensure components maintain their identity during updates. Having non-unique keys may result in duplicated or omitted children, which is not supported and might change in future versions.

Duplicate NaN values create duplicate keys.

It's recommended to use valueAsNumber and default to 0 if the value is absent.

const { useState, useEffect } = React;
const ReRendering = () => {
  const [number, setNumber] = useState(1);

  const getList = () => [number, number + 5, number + 10];

  return (
    <div>
      <input
        type="number"
        value={number}
        onChange={(e) => setNumber(e.target.valueAsNumber || 0)}
      />
      <div>
        <List getList={getList} />
      </div>
    </div>
  );
};

const List = ({ getList }) => {
  const [item, setItem] = useState([]);
  useEffect(() => {
    setItem(getList());
  }, [getList]);
  return (
    <div className="list">
      {item.map((x) => (
        <div key={x}>{x}</div>
      ))}
    </div>
  );
};


ReactDOM.render(<ReRendering />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class='react'></div>

A more effective way to organize this would be to directly call getList within the child component instead of using a separate state and effect hook inside it.

const { useState, useEffect } = React;
const ReRendering = () => {
  const [number, setNumber] = useState(1);

  const getList = () => [number, number + 5, number + 10];

  return (
    <div>
      <input
        type="number"
        value={number}
        onChange={(e) => setNumber(e.target.valueAsNumber || 0)}
      />
      <div>
        <List getList={getList} />
      </div>
    </div>
  );
};

const List = ({ getList }) => (
  <div className="list">
    {getList().map((x) => (
      <div key={x}>{x}</div>
    ))}
  </div>
);


ReactDOM.render(<ReRendering />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class='react'></div>

Answer №2

To achieve the desired outcome, implement the following modifications:

Essentially, the code snippet handles the scenario where the input is empty and specifies to display nothing when no input is provided.

List.js


import { useEffect, useState } from "react";

const List = ({ getList }) => {
  const [item, setItem] = useState([]);

  useEffect(() => {
    setItem(getList());
  }, [getList]);

  return (
    <div className="list">
      {item ? item.map((x) => (               // modifications
        <div key={x}>{x}</div>
      )) : ""}
    </div>
  );
};

export default List;


ReRendering.js

import React, { useState } from "react";
import List from "./List";

const ReRendering = () => {
  const [number, setNumber] = useState(1);

  const getList = () => {
    if(number === "") {                     // modifications
      return;
    }
    return [number, number + 5, number + 10];
  };

  return (
    <div>
      <input
        type="number"
        value={number}
        onChange={(e) => {
          if (e.target.value !== "") {               //modifications
            setNumber(parseInt(e.target.value, 10));
          } else {
            setNumber(""); 
          }
        }}
      />
      <div>
        <List getList={getList} />
      </div>
    </div>
  );
};

export default ReRendering;

Answer №3

When an input is empty, its value is simply an empty string. This causes issues for the parseInt function since it doesn't know how to handle it, resulting in a return of NaN. To resolve this, a function can be created to handle this scenario by setting the state to 0 if the input's value is empty. Here's an example:

const handleChange = (e) => {
  const value = e.target.value;
  setNumber(value === '' ? 0 : Number(value));
}

Additionally, I wanted to mention that you can simplify your code in the <List /> component by removing the unnecessary useState and useEffect. Since the list will update when the props change, you can directly map through the array like this:

getList().map(...rest of the code)

Answer №4

It appears that @CertainPerformance has already provided a solution to your query-

Please inform me if there are any errors in my approach.

After reviewing your feedback regarding the issue with zero in the input field, I suggest updating your getList() method by checking for numbers and returning an empty array if the number is blank.

The adjustment to your getList() function -

const getList = () => number ? [number, number + 5, number + 10] : [];

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The request to localhost resulted in a 404 error, indicating that the resource was not found

When attempting a file upload operation using MV.Net, I encountered the GET http://localhost:55298/Home/test2.json 404 (Not Found) error while trying to upload a file. How can this issue be resolved? <input type="file" name="file" ...

There have been no updates made to the SANITY Server while in Production Preview Mode

IMPLEMENTING 1 PROPERTY UPDATE IN A SCHEMATYPE Simply by including a single defineField: defineField({ name: 'surname', title: 'Surname', type: 'string', }), in an existing document named "author.ts", w ...

Alter the background of cards in real-time

I am unfamiliar with JavaScript, but I wish to utilize a function to alter the background color of multiple cards. function ChangeColorToGreen() { document.getElementById("ChangingCard").style.background = "green"; } function ChangeColorToPurple() { ...

Retrieve the attributes associated with a feature layer to display in a Pop-up Template using ArcGIS Javascript

Is there a way to retrieve all attributes (fields) from a feature layer for a PopupTemplate without explicitly listing them in the fieldInfos object when coding in Angular? .ts const template = { title: "{NAME} in {COUNTY}", cont ...

What is the best way to modify the appearance of the button?

I'm attempting to change the appearance of buttons at the top of a webpage to be square and blue. I have jQuery code for this purpose, but it doesn't seem to be functioning correctly. Here is the snippet of code I am using: $(document).ready(fu ...

Why does Vue 3 refuse to refresh an <img> element, while it successfully refreshes all other components within the same component?

In my current Vue project, I have set up multiple link cards (<a class='card'></a>) inside a "deck" container (<div class='deck'></div>). The implementation for these elements is relatively straightforward: <s ...

Updating the "title" attribute dynamically using jQuery in real time

I have a span that displays data in a tooltip every second, fetched from the server: <span class="info tooltip" title="{dynamic content}"></span> To show the tooltip, I'm using the tooltipsy plugin: $('.tooltip').tooltipsy({ ...

Obtain the location of the image source from a text file within an HTML document

I need to create a slideshow displaying a sequence of images. The path to these images will be stored in a text file. How can I read the image paths from the text file? Currently, I have hardcoded code like the example below: <div class="mySlides fade" ...

Switching Json to Typescript

I have a file named items.ts with the following interface: export interface item{ Name: string; IsSystemItem: string; ConfiguredSegments: ConfiguredSegments; } export interface ConfiguredSegments { LiveA: LiveA; } export interface LiveA { Weig ...

Creating a Personalized Color Palette Naming System with Material UI in TypeScript

I have been working on incorporating a custom color palette into my material ui theme. Following the guidance provided in the Material UI documentation available here Material UI Docs, I am trying to implement this feature. Here is an excerpt from my cod ...

Creating numerous pre-signed URLs using an Application Programming Interface

An API has been developed to generate pre-signed URLs for files stored in a private S3 bucket. The goal is to store these URLs in an array for access from another application. ["FILE1 pre-signed URL", "FILE2 pre-signed URL", etc..] However, there seems to ...

The issue with ng-bind-html causing the disappearance of paragraph spaces

Is there a way to preserve paragraph breaks when using ng-bind-html to display text on the screen? I am having an issue where all the text appears as one big chunk if there are paragraph breaks in the data pulled from the database. Not sure what is causing ...

Internet Explorer does not recognize window.opener.location as valid, while there are no issues with Chrome

Response.Write("<script language='javascript'>alert(window.opener.location.pathname); if(window.opener.location.pathname.toString() == \"/page.aspx\"){window.opener.document.forms[0].submit();}</script>"); While this code w ...

Finding out which carousel the user is currently engaging with in the Slick Carousel can be accomplished by following these steps

I am struggling with applying a class to the carousel container when the first slide is active in a page that contains multiple Slick carousels. Is there a way to update the code below so that the class is only applied to the specific carousel the user is ...

Accessing external content within our webpage

Previously, I utilized iframes to display an external page within our asp.net page. However, I have now decided to explore alternative methods that do not involve iframes. My goal is to open an external page within our page using only a simple aspx page wi ...

Unable to pass Ajax value to Laravel controller

Currently, I am facing an issue while trying to retrieve a value from an ajax request in my controller. Although my JavaScript function successfully displays the desired value in an alert, when I attempt to pass this value as data to the controller, it is ...

Guide on Deleting Specific Item Using SQL Data Source Delete Statement

I am facing an issue when trying to remove a specific item from a grid view in my SQL server database. I have configured DataKeyNames and linked a sql data source with the grid view. The delete command is set as follows: DeleteCommand="DELETE FROM product ...

Duplicate multiple "li" elements using jQuery and place them in a designated position within the ul element, rather than at the end

I am currently working on developing a dynamic pagination bar. This pagination bar will dynamically clone the "li" elements based on a number received from an external webservice. Here is the structure of my pagination element: <ul class="pagination"& ...

Leveraging geoPosition.js in conjunction with colobox

How can I create a colorbox link that prompts the user for permission to access their location, and if granted, displays a map with directions from their current location? I've managed to get it partially working, but there's an issue when the us ...

What is the process for obtaining the dimensions (height/width) of a particular instance within a dynamically rendered list?

[QUESTION REVISED FOR CLARITY] I am attempting to retrieve the dimensions, specifically the width and height, of a rendered <div/> within the Child.js component. While I found a helpful example on Stack Overflow, my scenario involves multiple dynami ...