New elements are not shown in the list after adding in React

Viewed 45

When the user clicks the plus button, I want the task array to appear as a list. I am not able to push my tasks to an array

import logo from './logo.svg';
import './App.css';
import { BsPlusLg } from "react-icons/bs";
import { useState } from 'react';

const App = () => {

  const items = ["Pizza", "Burger", "Shawarma", "Biryani", "Butter Naan", "Panner", "Chapathi"];

  let tasks = [];

  const [searchValue, setSearchValue] = useState("");

  const changeValue = (event) => {
    setSearchValue(event.target.value);
  }

  const searchedItems = tasks.filter((item) => {
    if(item.toLowerCase().includes(searchValue.toLowerCase())){
        return item;
      }
  })

  const handleClick = () => {
    if(items.length>0){
      tasks.push(items.pop());
    }
  }

On clicking the plus button, after the items are added to the tasks array, they should appear as a list.

  return (
    <div className="App">
      <div className='navbar'>
        <input type="text" value={ searchValue } onChange={ changeValue } placeholder="Search"></input>
        {/* <div className="verticalLine"></div> */}
        <button onClick={ handleClick }><BsPlusLg /></button>
      </div>
      <hr/>
      <div className='list'>
        <ul>
          {(searchValue.length>0)&&(searchedItems.map((item) => {
            return <li key={item}>{item}</li>}))
          }
          {(searchValue.length===0)&&(tasks.map((item) => {
            return <li key={item}>{item}</li>
          }))
          }
        </ul>
      </div>
    </div>
  );
}

export default App;

The elements in the tasks in the page are not being displayed when I log out of the tasks that are being pushed.

2 Answers

Clicking on your button does not update your component and will therefore rerender your list.

If if it would, it will run the whole function again and even call let tasks = []; again, which would reset your whole list. To update lists or whatever state you else need, you are required to use useState or similar hooks.

Because you also pop your items array, you might want to use two useState hooks and update them instead. Those will handle the internal state for you and isn't lost on a rerender. See https://reactjs.org/docs/hooks-state.html for more information. A solution might look like the following:

import "./styles.css";
import {useState} from 'react'


const BsPlusLg = () => <span >+</span>

const App = () => {

  const [items, setItems] = useState( ["Pizza", "Burger", "Shawarma", "Biryani", "Butter Naan", "Panner", "Chapathi"]);
  const [tasks, setTasks] = useState([]);

  
  const [searchValue, setSearchValue] = useState("");

  const changeValue = (event) => {
    setSearchValue(event.target.value);
  }

  // searchedItems will be updated on each rerender
  const searchedItems = tasks.filter((item) => {
    if(item.toLowerCase().includes(searchValue.toLowerCase())){
        return item;
      }
  })

  const handleClick = () => {
    if(items.length === 0){
      // keep it simple and stop execution
      return;
    }
    
    // enforce a new reference
    let newItems = [...items];
   
    let item = newItems.pop();

    // enforce a new tasks reference
    let newTasks = [...tasks, item];
      
    setItems(newItems);
    setTasks(newTasks);


  }
  return (
    <div className="App">
      <div className='navbar'>
        <input type="text" value={ searchValue } onChange={ changeValue } placeholder="Search"></input>
        {/* <div className="verticalLine"></div> */}
        <button onClick={ handleClick }><BsPlusLg /></button>
      </div>
      <hr/>
      <div className='list'>
        <ul>
          {(searchValue.length>0)&&(searchedItems.map((item) => {
            return <li key={item}>{item}</li>}))
          }
          {(searchValue.length===0)&&(tasks.map((item) => {
            return <li key={item}>{item}</li>
          }))
          }
        </ul>
      </div>
    </div>
  );
}

export default App;

Sandbox: https://codesandbox.io/s/confident-albattani-jf1z6f?file=/src/App.js:0-1655

It means that when React component be re-render, variables is not changed. you must define 'item' variable as state.

const [tasks, setTasks] = useState([]);

For push it:

setTasks([...tasks, item.pop()])
Related