使用React挂钩(useEffect和useRef)-为什么ref会在复选框更改时更新



这是一个从实际项目中模拟的模型
单击"撤消"按钮应将复选框的状态更改为用户更改复选框之前的状态
选中/取消选中复选框时,appRef.current将更新!为什么
App.jsx中的效果挂钩只调用一次,因为它的依赖项数组为空。

当您单击选中/取消选中所有按钮,然后尝试更改复选框并单击undo键时,会变得更加困惑,但这次它有效


App.jsx

import { useEffect, useRef, useState } from 'react'
import Box from './box'
const App = () => {
const [claims, setClaims] = useState()
const appRef = useRef()
const crudTrue = { Create: true, Read: true, Update: true, Delete: true }
const crudFalse = { Create: false, Read: false, Update: false, Delete: false }
const defaultClaims = {
resource1: { ...crudFalse },
resource2: { ...crudFalse, Read: true },
resource3: { ...crudFalse, Read: true },
resource4: { ...crudFalse }
}
useEffect(() => {
// this effect should be called once
// appRef should be set once
appRef.current = { ...defaultClaims }
setClaims({ ...defaultClaims })
}, [])
return (
<Box
claims={claims}
// cloning to be extra sure it is not mutated
boxRef={{ ...appRef }}
onChange={setClaims}
crudTrue={crudTrue}
crudFalse={crudFalse}
/>
)
}
export default App

box.jsx

import { createElement, useEffect, useRef } from 'react'
import CheckBox from './checkBox'
const Box = ({ claims, boxRef, onChange, crudTrue, crudFalse }) => {
const checkRef = useRef()
useEffect(() => (checkRef.current = boxRef.current), [boxRef])
const handleChange = ({ currentTarget: checkbox }) => {
const xclaims = { ...claims }
const parts = checkbox.name.split('-')
xclaims[parts[0]][parts[1]] = checkbox.checked
onChange(xclaims)
}
const handleAll = () => {
const xclaims = { ...claims }
let isAnyClaimFalse = Object.keys(xclaims).some((res) =>
Object.keys(xclaims[res]).some((c) => xclaims[res][c] === false)
)
for (let res in xclaims) xclaims[res] = isAnyClaimFalse ? { ...crudTrue } : { ...crudFalse }
onChange(xclaims)
}
const handleUndo = () => onChange(checkRef.current)
const renderChecks = () => {
const children = []
for (let res in claims)
for (let key in claims[res])
children.push(
<>
{key === 'Create' && res}
<CheckBox
key={res + '-' + key}
name={res + '-' + key}
label={key}
checked={claims[res][key]}
onChange={handleChange}
/>
{key === 'Delete' && <br />}
</>
)
return createElement('div', [], ...children)
}
return (
<>
<button onClick={handleUndo}>undo</button>
<button onClick={handleAll}>check/uncheck All</button>
{renderChecks()}
</>
)
}
export default Box

复选框.jsx

const CheckBox = ({ name, label, ...rest }) => (
<>
<input type='checkbox' id={name} name={name} {...rest} />
{label && <label htmlFor={name}>{label}</label>}
</>
)
export default CheckBox

输出可在此处导航,并且codesandbox

在您的代码中没有发现问题,因此我尝试用自己的解决方案来解决它。我完全更改了一些代码。也许如果你把它的一部分写回你的,你就会发现问题的根源。

以下是codesandbox链接:https://codesandbox.io/s/using-react-hooks-useeffect-useref-1odx68

最新更新