はじめに
不要なレンダリングを回避するための備忘録です。
よくないやりかた
NameList
のpropsにオブジェクトを直で渡してしまうと、someOtherState
が変化するたびにNameList
が再レンダーされてしまう。
NameList.tsx
...
export const NameList: React.FC<string[]> = ({names}) => {
return (
<>
{names.map((name, key) => (<div key={key}> {name} </div>))}
</>
)
}
Users.tsx
...
interface IUser {
name: string;
id: number;
}
const Users: React.FC<> = () => {
const [users,setUsers] = useState<IUser[]>(initialUsers)
const [someOtherState, setSomeOtherState] = useState<ISomething>(initialSomething)
return ( <NameList names={users.map(user => user.name)}> )
}
正しいやり方
NameList
のpropsに渡すオブジェクトをmemo化する。そうすればsomeOtherState
が変化してもNameList
は再レンダーされない。
NameList.tsx
...
export const NameList: React.FC<string[]> = ({names}) => {
return (
<>
{names.map((name, key) => (<div key={key}> {name} </div>))}
</>
)
}
Users.tsx
...
interface IUser {
name: string;
id: number;
}
const Users: React.FC<> = () => {
const [users,setUsers] = useState<IUser[]>(initialUsers)
const [someOtherState, setSomeOtherState] = useState<ISomething>(initialSomething)
// ここ!!
const names = useMemo(() => users.map(user => user.name), [users])
return ( <NameList names={names}> )
}