Home > Net >  How can I make each student add their own identifier tags?
How can I make each student add their own identifier tags?

Time:05-03

I'm reading from an API and displaying each student's information onto the web browser. My goal is to make each student have a text input field in which you are able to add a 'tag' for the specific student.

My problem: Currently, I have given each student a text input field but when I enter a 'tag' for ANY of the students, it only adds the tag to the FIRST student.


Home.jsx

import axios from 'axios';
import { useState, useEffect } from 'react';
import Students from '../components/Students';
import styles from "./Home.module.css";

const Home = () => {

  const [students, setStudents] = useState([]);
  const [filteredStudents, setFilteredStudents] = useState([]);

  const fetchStudents = async () => {
    const response = await axios.get(`https://api.hatchways.io/assessment/students`);
    setStudents(response.data.students);
    setFilteredStudents(response.data.students);
    console.log(response.data.students);

  }

  const searchStudentName = async (searchName) => { 
    const searchNameFiltered = searchName.toLowerCase();
    console.log(searchNameFiltered);
    
    if (searchNameFiltered === "") {
      fetchStudents();
      return;
    }

    var newArray = await students.filter((student) => {
      return student.firstName.toLowerCase().includes(searchNameFiltered)
      || student.lastName.toLowerCase().includes(searchNameFiltered);
    })

    await setFilteredStudents(newArray);
  }

  useEffect(() => {
    fetchStudents();

  }, [])

  return(
    <>
      <div>
        <input className={styles.nameSearchInput} type="text" placeholder="Search by name" onChange={(event) => searchStudentName(event.target.value) }/>
        {filteredStudents.map((student) => (
          <Students key={student.id} student={student} />
        ))}
      </div>
    </>
  )
  
}

export default Home;

Students.jsx

import { useState } from 'react';
import styles from "../views/Home.module.css";
import { v4 as uuidv4 } from 'uuid';
import AddIcon from '@mui/icons-material/Add';
import RemoveIcon from '@mui/icons-material/Remove';

const Students = ({student}) => {

  const [isShown, setIsShown] = useState(true);

  const findAverageGrade = arr => {
    let sum = 0;
    for (let i = 0; i < arr.length; i  ) {
      sum  = parseInt(arr[i]);
    }
    return sum / arr.length;
  }

  const addTag = (event) => {
    if (event.key === 'Enter') {
      document.getElementById("tag-output").innerHTML  = `
        <p id="tag">${event.target.value}</p>
      `;
      document.getElementById("tag-input").value = "";
    }    

  }

  return (
    <div key={student.email} className={styles.studentItem}>
      <img className={styles.studentImage} src={student.pic} />
      <div className={styles.studentInfoContainer}>
        <div className={styles.studentHeader}>
          <p className={styles.studentName}>{student.firstName.toUpperCase()} {student.lastName.toUpperCase()}</p>
          <button className={styles.expandBtn} onClick={() => {
            setIsShown(!isShown);
          }}>
            { isShown ? <AddIcon className={styles.expandBtn} /> : <RemoveIcon className={styles.expandBtn} /> }
          </button>
        </div>
        <ul className={styles.studentDetail}>
          <li>Email: {student.email}</li>
          <li>Company: {student.company}</li>
          <li>Skill: {student.skill}</li>
          <li>Average: {findAverageGrade(student.grades)}%</li>

          {!isShown ? <div>
            <table className={styles.gradesTable}>
              <tbody>
                {student.grades.map((grade) => (
                  <tr key={uuidv4()}>
                    <td>Test</td>
                    <td>{grade}%</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
          : null }
          <div id="tag-output"></div>
          <input id="tag-input" className={styles.addTagInput} type="text" placeholder="Add a tag" onKeyPress={(e) => addTag(e)}/>
        </ul>
      </div>
    </div>
  )
}

export default Students;

CodePudding user response:

use array state and append it with new values like this

play live code here live_demo

import React, { useState } from "react";

    export default function Main(props) {
      const [tags, setTags] = useState([]);
      return (
        <div className="App">
          <input
            type="text"
            onKeyDown={(e) => {
              if (e.key === "Enter" && !e.shiftKey && e.target.value !== "") {
                let val = e.target.value;
                e.target.value = "";
                setTags([...tags, val]);
              }
            }}
          />
          <div className="tags">
            <ol className="each-tag">
              {tags.map((tag, i) => {
                return <li key={i}>{tag}</li>;
              })}
            </ol>
          </div>
        </div>
      );
    }
  • Related