skip to Main Content

I created a project where a component shows a list of Employees.

MyEmployee component:

import { useState } from "react";

export default function MyEmployee({
  data = [],
  page = 1,
  size = 2,
  total = 0
}) {
  const [myEmployees, setMyEmployees] = useState(data);
  const [currPage, setCurrPage] = useState(page);
  const [rows, setRows] = useState(size);
  const [totalData, setTotalData] = useState(total);

  return (
    <>
      {console.log("data: ", data)}
      {console.log("myEmployees: ", myEmployees)}
      <h2>Some Employee</h2>
      {myEmployees.map((emp) => {
        console.log("iterate emp", emp);
        return (
          <div key={emp.id}>
            <span>{emp.name}</span>
            <span>{emp.email}</span>
          </div>
        );
      })}
      <button>{"<"}</button>
      <span>
        {currPage} of {Math.ceil(totalData / rows)}
      </span>
      <button>{">"}</button>
    </>
  );
}

then in App component I pass the props:

import { useEffect, useState } from "react";
import MyEmployee from "./MyEmployee";
import { getSomeData } from "./SomeService";

export default function App() {
  const [employees, setEmployees] = useState({});

  function getData() {
    const emp = getSomeData();
    console.log("emp: ", emp);
    if (emp?.status) {
      setEmployees(emp.data);
    }
    console.log("employees: ", employees);
  }

  useEffect(() => {
    getData();
  }, []);

  return (
    <div className="App">
      {console.log("employees: ", employees)}
      <MyEmployee
        data={employees?.someEmployeeData?.obj}
        page={employees?.someEmployeeData?.page}
        size={employees?.someEmployeeData?.size}
        total={employees?.someEmployeeData?.total}
      />
    </div>
  );
}

the props come from SomeService.js:

export function getSomeData() {
  return {
    status: true,
    message: null,
    data: {
      someEmployeeData: {
        page: 1,
        size: 2,
        total: 5,
        obj: [
          {
            id: 1,
            name: "Deas",
            email: "[email protected]"
          },
          {
            id: 2,
            name: "Joey",
            email: "[email protected]"
          }
        ]
      }
    }
  };
}

result

But i see that the props are not passed as the states in MyEmployee which initialized with the props have the deafult value. what did i miss / do wrong?

codesandbox

2

Answers


  1. You are passing in the props but not setting the state inside the component, since you want them in different variables. Try adding useEffect in MyEmployee.js

    const [myEmployees, setMyEmployees] = useState(data);
    const [currPage, setCurrPage] = useState(page);
    const [rows, setRows] = useState(size);
    const [totalData, setTotalData] = useState(total);
    
    useEffect(() => {
      setMyEmployees(data);
      setCurrPage(page);
      setRows(size);
      setTotalData(total);
    }, [data, page, size, total]);
    
    
    return (
      etc...
    
    Login or Signup to reply.
  2. When the component is initialized, every props that are loaded in are default value, so they are either undefined or the fallback value that you defined in the argument. These part specific.

    export default function MyEmployee({
      data = [],
      page = 1,
      size = 2,
      total = 0
    }
    

    So when the states in MyEmployee is initialized, they are initialized the fallback value that you have defined ([], 1,2, and 3). Since the only way to update the state is to use setState method, all of the state like myEmployees and currPage are not being updated.

    The proper way is to not store them as state and read them directly, and get the updated values from the parent component that passes those values in as props.

    Of course, the other alternative would be to use the useEffect to update those states with useState when the props are updated, but that will cause many unnecessary re-render as a caveat.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search