React useState 钩子影响状态中使用的默认变量,而不管传播运算符,Object.assign 等

React useState hook affecting default variable used in state regardless spread operators, Object.assign and etc

我是经验丰富的 js/React 开发人员,但遇到了我无法解决的案例,我不知道如何解决它。

我有一个具有许多不同状态的上下文提供程序,但其中一种状态如下所示:

const defaultParams = {
  ordering: 'price_asc',
  page: 1,
  perPage: 15,
  attrs: {},
}

const InnerPageContext = createContext()

export const InnerPageContextProvider = ({ children }) => {
  const [params, setParams] = useState({ ...defaultParams })

  const clearParams = () => {
    setParams({...defaultParams})
  }

  console.log(defaultParams)

  return (
    <InnerPageContext.Provider
      value={{
        params: params,
        setParam: setParam,
        clearParams:clearParams
      }}
    >
      {children}
    </InnerPageContext.Provider>
  )
}

我在页面上有一个按钮,它调用 clearParams 函数,它应该将参数重置为默认值。 但它不起作用

即使我 console.log(defaultParams) 在每个提供程序重新呈现时,似乎 defaultParams 变量也在状态更改时更改

我认为这不正常,因为我使用了{...defaultParams},它应该创建新变量,然后将其传递给useState hook。

我试过:

const [params, setParams] = useState(Object.assign({}, defaultParams))
const clearParams = () => {
  setParams(Object.assign({}, defaultParams))
}
const [params, setParams] = useState(defaultParams)
const clearParams = () => {
  setParams(defaultParams)
}
const [params, setParams] = useState(defaultParams)
const clearParams = () => {
  setParams({
    ordering: 'price_asc',
    page: 1,
    perPage: 15,
    attrs: {},
  })
}
上述方法的

None 有效,但第 3 次我硬编码了与 defaultParams 相同的对象。 这个想法是将dafult参数保存在某个地方,当用户清除参数时将恢复到它。 你们有什么想法吗?

编辑: 这就是我更新参数的方式:

const setParam = (key, value, type = null) => {
    setParams(old => {
      if (type) {
        old[type][key] = value
      } else old[key] = value
      console.log('Params', old)
      return { ...old }
    })
  }

请说明如何更新“参数”。

如果代码“params.attrs.test = true”中有这样的内容,那么默认参数将被更改

如果old[type]不是简单类型,它在defaultParams中存储对同一对象的引用。 defaultParams.attrs === params.attrs。因为在初始化过程中你解构了一个对象而不是它的嵌套对象。

问题在这里:old[type][key] = value

解决方案:

const setParam = (key, value, type = null) => {
    setParams(old => {
      if (type) {
        old[type] = {
          ...old[type],
          key: value,
        }
      } else old[key] = value
      return { ...old }
    })
  }