首页 > 解决方案 > ReactJs,在全局状态更改时丢失子组件本地状态

问题描述

我不了解一些 ReactJs 行为,需要一些帮助。

我有一个根功能组件(“索引”),其中包含另一个功能组件(“预览”)。该预览组件包含几个其他功能组件(“InlineField”)。

该应用程序是一个简单的表单,其中 InlineField 是呈现输入的组件,还包含一个状态以了解该字段是“打开”还是“关闭”(关闭时显示为文本,打开时显示为输入)。

全局状态是使用钩子和“索引”级别定义的,并通过道具向下移动到字段(我已经尝试过使用上下文)。此状态包含所有表单值。

InlineField 组件使用钩子仅维护其本地状态(打开/关闭)。当输入改变时,它会更新状态(索引级别),这会触发索引及其子项的重新渲染。这将转换为当前编辑的字段(本地状态 = 打开的 InlineField 组件)以刷新并丢失其状态值。

我的问题: 如何确保这些 InlineField 组件即使在更新全局状态后仍保持其状态?我也可以简单地将 InlineField 组件状态移动到全局状态,但我认为这没有多大意义。

我一定是搞错了……

谢谢!


编辑:添加代码示例

指数成分:

import React, { useState, useEffect } from "react"

import Layout from "../components/layout"


const IndexPage = () => {


  const [formValues, setFormValues] = useState({
    name: 'Myname',
    email: 'myemail@mail.com',
  })

  const onFormValueChange = (key, value) => {
    setFormValues({...formValues, [key]: value})
  }

  return (
    <Layout>
      <Preview
        key="previewyaknow"
        formValues={formValues}
        onFieldChange={setFormValues}
      />
    </Layout>
  )
}
export default IndexPage

预览组件:

import React from 'react'
import { Box, TextField } from "@material-ui/core"
import { InlineField } from './inlineField'

export const Preview = ({formValues, onFieldChange}) => {

  return (
    <>
      <Box display="flex" alignItems="center">
        <InlineField 
          value={formValues.email}
          onChange={onFormValueChange}
          id="email"
          field={<TextField value={formValues.email}/>>>}
        />
    </>
  )
}

内联编辑组件

import React, { useState, useEffect } from "react"

export const InlineField = ({onChange, value, id, field}) => {
  const [isEdit, setIsEdit] = useState(false)

  const onBlur = (e) => {
    setIsEdit(false)
  }

  let view = (<div>{value}</div>);
  if (isEdit) { 
    view = (
      <FieldContainer className={classes.fieldContainer}>
        {React.cloneElement(field, { 
          'onBlur': onBlur, 
          'autoFocus': true, 
          'onChange': (e) => {
            onChange(id, e.target.value) 
          }
        })
        }
      </FieldContainer>
    )
  }

  return (
    <div onClick={()=>setIsEdit(!isEdit)}>
      {view}
    </div>
  )
}

标签: javascriptreactjs

解决方案


推荐阅读