React Компонент перерендерывается, когда он мемоизирован через React.memo(), и пропс onClick сделан через useCallback()
import React from 'react';
import { useState, memo, useCallback } from 'react';
import reactLogo from './assets/react.svg';
import viteLogo from '/vite.svg';
import './App.css';
// import Button from './components/Button';
const Button2 = ({ children, onClick, ...args }) => {
console.log('Button render');
return (
<button onClick={onClick} {...args}>
{children}
</button>
);
};
function App() {
const [count, setCount] = useState(0);
const [input, setInput] = useState('');
const MemoButton = React.memo(Button2);
const handleInput = useCallback((e) => {
setInput(e.target.value);
});
const handleClickButton = useCallback(() => {
console.log('callback start');
setCount((count) => count + 1);
}, [setCount, count]);
return (
<>
<div>
<a href="https://vitejs.dev" target="_blank">
<img src={viteLogo} className="logo" alt="Vite logo" />
</a>
<a href="https://react.dev" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
</div>
<h1>Vite + React</h1>
<div className="card">
<input type="text" value={input} onChange={handleInput} />
<MemoButton onClick={handleClickButton}>+</MemoButton>
<button>count is {count}</button>
</div>
</>
);
}
export default App;
сделал мемоизацию компонента и useCallback для пропса
а если сделать мемоизацию компонента сразу
const Button = React.memo(({ children, onClick, ...args }) => {
console.log('Button render');
return (
<button onClick={onClick} {...args}>
{children}
</button>
);
})
то все работает, но мемоизировать компонент навсегда, думаю по оптимизации не хорошо, можно ли сделать мемоизацию для импортированного компонента?
Ответы (1 шт):
Автор решения: SwaD
→ Ссылка
Для того, что бы мемоизировать компонент в компоненте, необходимо использовать хук useMemo:
const buttonMemo = useMemo(() => <Button2 onClick={() => setCount(c => c + 10)}>
{buttonState}
</Button2>,
[buttonState]);
Хук будет проверять массив зависимостей. Если значение в массиве зависимостей изменится, то будет пересчитано значение функции колбэка, иначе, возвращено сохраненное предыдущее значение(В данном примере, это JSX компонент)
Пример полного компонента
import React, { useState, useMemo } from 'react'
const Button2 = ({ children, onClick, ...args }) => {
console.log('Button render');
return (
<button onClick={onClick} {...args}>
Изменено {children} раз
</button>
);
};
const App = () => {
const [count, setCount] = useState(0);
const [buttonState, setButtonState] = useState(0);
console.log('render app');
const buttonMemo = useMemo(() => <Button2 onClick={() => setCount(c => c + 10)}>
{buttonState}
</Button2>, [buttonState]);
return (
<>
<button onClick={() => setCount(count + 1)}>
Нажато без изменений мемокнопки {count}
</button>
{buttonMemo}
<button onClick={() => setButtonState(c => ++c)}>Нажать для изменения мемокнопки</button>
</>
)
}
export default App
Этот же пример в песочнице