skip to Main Content

Hello I got my react page code to edit user profile it has a dropdown selector from react-select library and an input text box. as for my state management i use zustand. My page run just fine for its purpose and function but when i add my dropdown component i realized it re render too much.

is there any possible way to improve my code so it wont cause too much re render?

this is my code

srcapp(dashboard)my-profilepage.tsx

"use client";
import InputTexColProfile from "@/app/(dashboard)/my-profile/components/inputTextBoxCol";
import DDSearch from "@/app/(dashboard)/my-profile/components/DDSearch";
import changeHandler from "./scripts/changeHandlerDD";
import { useEffect } from "react";
import { userStore } from "@/stores/userStore";
import { organisasiStore } from "@/stores/organisasiStore";
import { fetchListUser } from "@/stores/userStore";
import TextInputHandler from "./scripts/changeHandlerInput";

const UserProfile = () => {
  const { user, listUsers } = userStore((state) => state);
  const { fetchOrganisasi, direktorat, departemen, divisi } = organisasiStore(
    (state) => state
  );

  useEffect(() => {
    if(!listUsers){
      fetchListUser()
    }
    if(!direktorat || !departemen || !divisi){
      fetchOrganisasi();
    }
  }, []);

  console.log('render user profile')

  // if (user && direktorat && departemen && divisi && listUsers) {
    return (
      <div className="flex-col w-full h-full max-h-[100%] justify-center">
        <div className="flex justify-center p-5">
          {!user?.adminValidation ? (
            <p className="text-wrap text-center text-xl font-extrabold text-[#A70000] w-[40%]">
              Akun anda belum tervalidasi oleh Admin Mohon buat request dan
              hubungi admin layum
            </p>
          ) : (
            <p className="text-wrap text-center text-xl font-extrabold text-lightblue w-[40%]">
              Akun anda telah tervalidasi
            </p>
          )}
        </div>
        <div className="flex gap-2 justify-evenly mx-auto h-[70%] w-[80%] bg-lightblue rounded-[20px]">
          <div className="grid grid-rows-3 rounded-[20px] w-[45%] my-auto h-[80%] items-center bg-lighterblue">
            <InputTexColProfile
              label="name"
              text="Nama"
              defaultVal={user?.name}
              TextInputHandler={TextInputHandler}
              disabled={false}
            />
            <DDSearch
              label="atasan"
              text="Nama Atasan"
              isMulti={false}
              dataArr={listUsers}
              changeHandler={changeHandler}
            />
            <InputTexColProfile
              label="jabatan"
              text="Jabatan"
              defaultVal={user?.jabatan}
              TextInputHandler={TextInputHandler}
              disabled={false}
            />
          </div>
          <div className="grid grid-rows-3 rounded-[20px] w-[45%] my-auto h-[80%] items-center bg-lighterblue">
            <DDSearch
              label="direktorat"
              text="Direktorat"
              isMulti={false}
              dataArr={direktorat}
              changeHandler={changeHandler}
            />
            {/* <DDSearch
              label="divisi"
              text="Divisi"
              isMulti={false}
              dataArr={divisi}
              changeHandler={changeHandler}
            /> */}
            {/* <DDSearch
              label="departemen"
              text="Departemen"
              isMulti={false}
              dataArr={departemen}
              changeHandler={changeHandler}
            /> */}
          </div>
        </div>
      </div>
    );
  // } else {
  //   return <h1>Loading</h1>
  // }
};

export default UserProfile;

srcapp(dashboard)my-profilecomponentsDDSearch.tsx

import React from "react";
import LabelBox from "@/app/(dashboard)/my-profile/components/LabelBox";
import dynamic from "next/dynamic";
const Select = dynamic(() => import('react-select'), {
  ssr: false,
})

interface Props {
  isMulti: boolean;
  dataArr: any;
  label: string;
  text: string;
  changeHandler: (context: string, data: any) => void
}

interface OptionsE {
  value: any;
  label: string;
}

type Options = OptionsE[];

const DDSearch = ({ label, text, isMulti, dataArr, changeHandler }: Props) => {
  console.log('render ' + label)
  let options: Options
  if (Array.isArray(dataArr)) {
    options = dataArr.map((e) => {
      return {
        value: e,
        label: `${e.name}`,
      };
    });
    return (
      <div className="flex-col w-full justify-start ms-5 max-w-[90%]">
        <LabelBox forLabel={label} text={text} />
        <Select
          id={label}
          isMulti={isMulti}
          options={options}
          onChange={(e: any) => {
            changeHandler(label, e.value);
          }}
          name="colors"
        />
      </div>
    );
  }
};

export default DDSearch;

srcapp(dashboard)my-profilescriptschangeHandlerDD.ts

import { setUser, userStore } from "@/stores/userStore";

const changeHandler = (context: string, data: any) => {
  const userdata = userStore.getState().user;
  let obj: any;
  switch (context) {
    case "atasan":
      obj = {
        ...userdata,
        atasan: data.name,
      };
      setUser(obj);
      return;

    case "direktorat":
      obj = {
        ...userdata,
        direktorat: data.name,
      };
      setUser(obj);
      return;

    case "divisi":
      obj = {
        ...userdata,
        divisi: data.name,
      };
      setUser(obj);
      return;
      
    case "departemen":
      obj = {
        ...userdata,
        departemen: data.name,
      };
      setUser(obj);
      return

    default:
      return;
  }
};

export default changeHandler;

Thanks before

2

Answers


  1. cool new

    import { setUser, userStore } from "@/stores/userStore";
    
    const changeHandler = (context: string, data: any) => {
      const userdata = userStore.getState().user;
      let obj: any;
      switch (context) {
        case "atasan":
          obj = {
            ...userdata,
            atasan: data.name,
          };
          setUser(obj);
          return;
    
        case "direktorat":
          obj = {
            ...userdata,
            direktorat: data.name,
          };
          setUser(obj);
          return;
    
        case "divisi":
          obj = {
            ...userdata,
            divisi: data.name,
          };
          setUser(obj);
          return;
          
        case "departemen":
          obj = {
            ...userdata,
            departemen: data.name,
          };
          setUser(obj);
          return
    
        default:
          return;
      }
    };
    
    export default changeHandler;
    Login or Signup to reply.
  2. Your code looks generally well-structured, but you’re experiencing excessive re-renders, especially when using the DDSearch component from react-select. Here are a few suggestions to optimize your code:

    1. Memoize Change Handlers: Memoize your change handlers using the useCallback hook. This will ensure that the functions are not recreated on each render, reducing unnecessary re-renders.

      jsxCopy codeconst changeHandler = useCallback((context: string, data: any) => {
        // Your existing code
      }, []); // Empty dependency array means this callback will not change over time
      
      
    2. Optimize DDSearch Component: Ensure that the DDSearch component only renders when its props (dataArr) change. Wrap it with React.memo to memoize the component.

      jsxCopy codeconst DDSearch = React.memo(({ label, text, isMulti, dataArr, changeHandler }: Props) => {
        // Your existing code
      });
      
      
    3. Reduce Logging: You have several console.log statements in your components. While helpful for debugging, excessive logging can impact performance. Remove or minimize logging, especially in components that render frequently.

    4. Ensure fetchListUser and fetchOrganisasi are memoized: If these functions are recreated on each render, consider using useCallback to memoize them.

      jsxCopy codeconst fetchListUserMemoized = useCallback(() => {
        fetchListUser();
      }, [fetchListUser]);
      
      const fetchOrganisasiMemoized = useCallback(() => {
        fetchOrganisasi();
      }, [fetchOrganisasi]);
      
      

      Ensure that you call fetchListUserMemoized and fetchOrganisasiMemoized in your useEffect.

    By incorporating these optimizations, you should be able to reduce unnecessary re-renders and improve the performance of your React application.

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