[英]React redux - parent state changing, but child components not re-rendering
[英]Changing one state in an array causes a re-rendering of the entire loop-generated custom components in React Hooks
我正在使用 React Hooks。 我正在從地圖填充按鈕列表。 每個按鈕在disabled
屬性上都有自己的狀態。 在填充它們之后,當單擊一個按鈕時,我想將該按鈕設置為禁用。
const initialBtnDisabled = [false, false, false, false, false, false, false, false];
const [btnDisabled, setBtnDisabled] = useState(initialBtnDisabled);
const onChange = event => {
const btnIndex = event.target.value;
let btnDisabledcopy = [...btnDisabled]
btnDisabledcopy[btnIndex] = true
setBtnDisabled(btnDisabledcopy)
}
const Button = (props) => {
console.log("I am from button");
const { btnIndex } = props
return (
<button onClick={onChange} value={btnIndex} disabled={btnDisabled[btnIndex]}>click me</button>
)
}
const btnArr = [1, 2, 3, 4, 5, 6, 7, 8]
const btnFields = btnArr.map((item, index) =>
<td key={index}>
<Button btnIndex={index} />
</td>
);
return (
<tr>{btnFields}</tr>
)
現在這可行,但問題在於每次單擊按鈕時,Button 組件將再次為整個循環重新渲染,而我只更改了數組的一個狀態。 我在Button
組件中的console.log
每次點擊都會記錄 8 次。
我如何防止這種情況?
您可以使用 React PureComponent 防止重新渲染。 如果傳遞的道具被更新,這只會重新渲染組件。
const initialBtnDisabled = [false, false, false, false, false, false, false, false];
const [btnDisabled, setBtnDisabled] = useState(initialBtnDisabled);
const onChange = event => {
const btnIndex = event.target.value;
let btnDisabledcopy = [...btnDisabled]
btnDisabledcopy[btnIndex] = true
setBtnDisabled(btnDisabledcopy)
}
class Button extends React.PureComponent {
render () {
console.log("I am from button");
const { btnIndex } = this.props;
return (
<button onClick={onChange} value={btnIndex} disabled={btnDisabled[btnIndex]}>click me</button>
)
}
}
const btnArr = [1, 2, 3, 4, 5, 6, 7, 8]
const btnFields = btnArr.map((item, index) =>
<td key={index}>
<Button btnIndex={index} />
</td>
);
return (
<tr>{btnFields}</tr>
)
您的按鈕正在重新渲染,因為它們的道具正在發生變化。
通過將Button
定義移到渲染函數之外,您可以像這樣實現:
const Button = memo(props => { console.log('I am from button') const { btnIndex, onClick, disabled } = props return ( <button onClick={() => onClick(btnIndex)} value={btnIndex} disabled={disabled} > click me </button> ) }) function App() { const initialBtnDisabled = [ false, false, false, false, false, false, false, false, ] const [btnDisabled, setBtnDisabled] = useState(initialBtnDisabled) const btnDisabledRef = useRef(btnDisabled) btnDisabledRef.current = btnDisabled const onClick = useCallback(btnIndex => { let btnDisabledcopy = [...btnDisabledRef.current] btnDisabledcopy[btnIndex] = true setBtnDisabled(btnDisabledcopy) }, []) const btnArr = [1, 2, 3, 4, 5, 6, 7, 8] const btnFields = btnArr.map((item, index) => ( <td key={index}> <Button btnIndex={index} onClick={onClick} disabled={btnDisabled[index]} /> </td> )) return <tr>{btnFields}</tr> } const rootElement = document.getElementById('root') ReactDOM.render(<App />, rootElement)
注意使用useRef
來跟蹤狀態的當前值。 這允許我們指定[]
作為依賴項
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.