ReactJS:Child 组件 re-rendering 来自 parent 的 OnChange 事件

ReactJS: Child component re-rendering on OnChange event from parent

我有一个包含两个 children 的 parent 组件:显示信息的 Child1 和通过输入更改信息的 Child2。我的目标是保持 Child1 的信息来自 re-rendering,直到保存触发器从 Child2 传递到 parent,这意味着数据已保存。为此,我在 Child1 中使用 memo 来记忆数据并将其保存在 re-rendering 中,但它不会起作用,因为每次触发 onChange 事件时 child 仍然是 re-rendered。如何让 Child1 在保存之前保持数据不变?这是我目前所拥有的:

孩子 1:

import React,{memo} from 'react'

const UserDetails = ({values,onOpen})=>{

console.log("child1 rendering")
    return(
          <Center>
            <Box d="flex" justifyContent='space-between' w="xs">
              <Heading name="username">{values.username}</Heading>
              <IconButton size="md" icon={<FiPenTool />} onClick={onOpen} />
            </Box>
          </Center>
          <Stack mt={10} direction={['column', 'column']}>
            <Heading fontSize="20px">Location:{values.location}</Heading>

            <Box mt={5} px={20}>
              <Heading fontSize="20px">Description</Heading>
              <Text fontSize="md">{values.description}</Text>
            </Box>
          </Stack>
    )
}

export default memo(UserDetails)

孩子 2:

      function PopUpDetails({ values, handleDetails })

 {
    console.log("child2 render")
  return (
        <Box>
        <Input name="username" w="md" mt={5} mr={5} fontWeight="bold" textAlign="center"
          value={values.username} onChange={handleDetails} />
        <Input name="location" mt={5} fontWeight="bold" onChange={handleDetails} 
          textAlign="center" 
          w="md" mr={5}
           onFocus={() => onOpen()} value={values.location} />
         
        <Input name="description" w="md" h="20vh" mt={5} mr={5} textAlign="center"
        fontWeight="bold" value={values.description} onChange={handleDetails} />
      
    </Box>
  )

}

export default PopUpDetails

Parent:

const userValues= {
  username: '',
  location:'',
  description:''
}

function User() {
  const { Moralis, user, setUserData, isUserUpdating } = useMoralis()
  const currentUserId = user.id
  const { isOpen, onOpen, onClose } = useDisclosure()
  const params = { "userId": currentUserId }
  const [details, setDetails] = useState(()=>()=>userHook())

 const userHook = useCallback(()=>{ //callback function to retrieve initial values each  time 
                                        user closes child2 in case data was not saved
   setDetails({...details,
    username:Moralis.User.current().attributes.username,
    description: Moralis.User.current().attributes.description,
    location: Moralis.User.current().attributes.location,
  })
  },[])

  useEffect(()=>{
    userHook()
  },[])

  const saveDetails = () =>{
    setUserData({
      location: details.location,
      username: details.username,
      description: details.description,
    })
  }

 const handleInputChange = (e) => {
    const { name, value } = e.target
    setDetails({
      ...details,
      [name]: value
    })
  }

return(
  <Container>
   <UserDetails values={details}/>
    <Modal isOpen={isOpen} size="3xl" closeOnOverlayClick isCentered onClose={() => { onClose();userHook()}}>
        <ModalOverlay />
        <ModalContent >
          <ModalHeader>Edit details</ModalHeader>
          <ModalCloseButton />
          <ModalBody>
            <PopUpDetails values={details} handleDetails={(e) => handleInputChange(e)}/>
          </ModalBody>
          <ModalFooter>
            <Button onClick={() => saveDetails()} variant='ghost'>Save</Button>
          </ModalFooter>
        </ModalContent>
      </Modal>
   </Container>
)

export default User

谁能帮助我理解为什么 Child1 re-renders 每次即使我使用备忘录,我如何缓存数据以便在触发 handleChange 时它不会反映在 Child1 上?任何帮助将不胜感激!

<UserDetails values={details}/>

您的用户详细信息正在接收“值”prop 中的状态,这是您在模式中更改的状态,那么您为什么不希望重新呈现?

尝试将您的初始值放在一边,然后将其设置为默认状态并将其传递给您的组件以保持不变。

function User() {
  const { Moralis, user, setUserData, isUserUpdating } = useMoralis()
  const { isOpen, onOpen, onClose } = useDisclosure()
  const params = { "userId": user.id }
  const initValues = useMemo(() => {
    const {
      username,
      description,
      location
    } = Moralis.User.current().attributes;
    return { username, description, location };
  }, []);
  const [details, setDetails] = useState(initValues)

  ...

    <UserDetails value={initValues}  />

  ...