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
cool new
Your code looks generally well-structured, but you’re experiencing excessive re-renders, especially when using the
DDSearch
component fromreact-select
. Here are a few suggestions to optimize your code: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.Optimize
DDSearch
Component: Ensure that theDDSearch
component only renders when its props (dataArr
) change. Wrap it withReact.memo
to memoize the component.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.Ensure
fetchListUser
andfetchOrganisasi
are memoized: If these functions are recreated on each render, consider usinguseCallback
to memoize them.Ensure that you call
fetchListUserMemoized
andfetchOrganisasiMemoized
in youruseEffect
.By incorporating these optimizations, you should be able to reduce unnecessary re-renders and improve the performance of your React application.