저는 현재 Hooks로 React App을 만들고 있습니다. 어딘가에서 데이터를로드하고 한편으로는 데이터를 표시하고 다른 한편으로는 데이터를 대체하는 구성 요소 ( Clicker, ClickerDisplay )를 동적으로 생성 하는 구성 요소 ( View )가 있습니다.
앱은 기본적으로 작동하지만 내 관심사는 그것 의 성능 입니다. 내 상태는 100ms마다 업데이트되며 변경시 모든 것이 다시 렌더링되면 큰 오버 헤드가 될 것입니다.
변경해야하는 구성 요소 만 다시 렌더링 할 수 있습니까?
나에게 매우 추한 또 다른 것은 내 상태를 업데이트하는 방법입니다. setState([...state]);
더 나은 방법이 있습니까?
사이드 노트 :
내 예제 코드에서 id는 현재 항목 속성을 하위 구성 요소로만 전달하고 있지만 전체 항목을 하위 구성 요소로 전달할 계획입니다.
또한 앱의 상태를 빌드하고 하나의 큰 JSON 개체에 저장해야하므로 상위 구성 요소에 기본 상태 를 유지하고 싶습니다 .
데이터
//Some Random Data
const things = [
{
"id": 0,
"name": "thing 1",
},
{
"id": 1,
"name": "thing 2",
},
{
"id": 2,
"name": "thing 3",
}
];
View.js
export default function View(props) {
const tmp = things.map(item => {
return { ...item, amount: 0 };
});
const [state, setState] = useState(tmp);
//alternates the amount and updates the state
function updateAmount(item, newAmount) {
item.amount = newAmount;
setState([...state]);
}
function createClicker(item) {
const { name, amount } = item;
return (<Clicker
name={name}
amount={amount}
clicked={() => updateAmount(item, amount + 1)} />
);
}
function createClickerDisplay(item) {
const { name, amount } = item;
return (<ClickerDisplay
name={name}
amount={amount} />
);
}
return (
<ul>
{state.map(item =>
<li>
{createClicker(item)} = {createClickerDisplay(item)}
</li>
)}
</ul>
);
}
Clicker.js
//component to alternate data
function Clicker(props) {
const { clicked, name, amount } = props;
return <button onClick={() => clicked(name)}>{name}: {amount}</button>;
}
ClickerDisplay.js
//component to display data
function ClickerDisplay(props) {
const { name, amount } = props;
return <span>{name}: {amount}</span>;
}
상태 및 소품의 특정 변경 사항을 기반으로 조건부로 다시 렌더링하도록 구성되지 않은 경우 React 구성 요소는 모든 라이프 사이클에서 다시 렌더링됩니다. 귀하의 경우 기능적 구성 요소를 사용하고 React.memo()
있으므로 이러한 구성 요소를 메모하는 데 활용할 수 있습니다 . 즉, 전달 된 props 내부의 값이 변경되는 경우에만 렌더링됩니다. 복잡한 구조가있는 경우 기본 비교기는 얕은 비교 만 수행하지만주의해야합니다.
아래 스 니펫은 메모 된 구성 요소의 사용을 보여주고 클릭 이벤트 핸들러의 일부로 수행중인 상태 변형을 해결합니다.
const things = [
{ "id": 0, "name": "thing 1" },
{ "id": 1, "name": "thing 2" },
{ "id": 2, "name": "thing 3"}
];
function Clicker({ clicked, name, amount }) {
return <button onClick={() => clicked(name)}>{name}: {amount}</button>;
}
// Memoized component that only updates when its simple props change
const ClickerDisplayMemoized = React.memo(function ClickerDisplay(props) {
const { name, amount, index } = props;
console.log(`Updating ClickerDisplay ${index + 1}`);
return <span>{name}: {amount}</span>;
});
function View() {
const thingsWithAmounts = things.map((item) => ({ ...item, amount: 0 }));
const [state, setState] = React.useState(thingsWithAmounts);
// Updated callback that avoids state mutation
function updateAmount(index, newAmount) {
setState(state.map((item, i) => ({
...item,
amount: (i === index ? newAmount : item.amount)
})));
}
const createClicker = ({ name, amount }, index) => (
<Clicker name={name} amount={amount}
clicked={() => updateAmount(index, amount + 1)} />
);
const createClickerDisplay = ({ name, amount }, index) => (
<ClickerDisplayMemoized name={name} amount={amount} index={ index } />
);
return (
<ul>
{state.map((item, i) => (
// this component needs a key as it's part of a map()
<li key={ i }>
{createClicker(item, i)} = {createClickerDisplay(item, i)}
</li>
))}
</ul>
);
}
ReactDOM.render(<View />, document.getElementById('root'));
/* this is just so the console in this snippet doesn't cover the components */
.as-console-wrapper { max-height: 50% !important; }
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다