具有子组件的更新对象应如何反映在父组件上

How updated object with child component should reflect on parent component

我想在机器阵列中添加机器,所以我定义了一个具有添加功能的特定组件。因此,当我在“进程”数组中添加“进程”时,它会使用 useEffect 反映在控制台上。但是当我添加一台机器时,它会反映在 MachineGround Component 但不会反映在 App 组件中。总的来说,我计划添加一个仪表板,即使在机器阵列中添加了一个 mcahine,它也应该反映在应用程序组件的进程中,并且应该更新仪表板。

非常感谢你的帮助。

应用组件

import React, { useEffect, useState } from 'react';
import { Container, Typography, Box, Button } from '@mui/material'
import MachineGround from './Components/MachineGround'


import { Process } from './types'

const App = () => {


  const [processes, setProcesses] = useState<Process[]>([{
    Name: 'Process-1', machines: [
      {
        Name: 'Machine-1', devices: [{
          Name: 'device-1',
          type: 'Timer'
        }]
      }]
  }])  // dummy process
  // const [processes, setProcesses] = useState<Process[]>([])
  const [count, setCount] = useState<number>(1) // dummy process count.


  // Add Process
  const addProcess = () => {

    if (processes.length < 10) {
      setCount(count + 1)
      const processNow: Process = {
        Name: `Process-${count}`,
        machines: []
      }
      setProcesses((process) => {
        return (
          [...process, processNow]
        )
      })
    } else {
      alert("Limit can't exceeds 10")
    }

  }


  // Delete Process
  const deleteProcess = (passProcess: Process) => {
    setProcesses(processes.filter((process) => process.Name !== passProcess.Name))
  }



  useEffect(() => {
    console.log(processes)
  }, [processes])

  return (
    <>
      <Container maxWidth='lg'>
        <Typography variant='h3' mt={5} sx={{ fontWeight: 700 }} align={'center'} gutterBottom>
          My DashBoard
        </Typography>

        <Box sx={{ bgcolor: '#F4F4F7', paddingInline: 5, borderRadius: 10 }} >
          {/* here will be the renders of processes */}
          {
            processes.map((process) => (
              <Box>
                <Box sx={{ display: 'flex', justifyContent: 'space-between' }} pb={2} pt={2}>
                  <Typography variant='h6'  >
                    {process.Name}
                  </Typography>
                  <Button variant='contained' onClick={() => {
                    deleteProcess(process)
                  }}>
                    Delete
                  </Button>
                </Box>
                <MachineGround process={process} />
              </Box>
            ))
          }
        </Box>

        <Button variant='contained' color='primary' sx={{ marginBlock: 5, marginLeft: 10 }} onClick={addProcess}> Add Process</Button>
      </Container>
    </>
  );
}

export default App;
import React, { useEffect, useState } from 'react'
import DeviceGround from './DeviceGround'
import { Box, Typography, Button } from '@mui/material'

//types
import { Machine, Process } from '../types'


type Props = {
    process: Process
}


const MachineGround = ({ process }: Props) => {


    const [count, setCount] = useState<number>(1)
    const [machines, setMachines] = useState<Machine[]>(process.machines)

    const handleAddMachine = () => {
        if (machines.length < 10) {
            const newMachine: Machine = { Name: `Machine-${count}`, devices: [] }
            setMachines((machines) => [...machines, newMachine])
            setCount(count + 1)
        } else {
            alert("You can't add more than 10 Machines.")
        }
    }

    const handleDeleteMachine = (machine: Machine) => {
        setMachines(machines.filter((current) => current.Name !== machine.Name))
    }

    useEffect(() => {
        console.log('machines Array Changed')
    }, [machines])


    return (
        <Box sx={{ bgcolor: '#00e676', borderRadius: 5 }} mt={2} ml={3} mr={3} pt={1} pb={1} mb={2}>
            {machines.map((machine: Machine) => {
                return (
                    <>
                        <Box sx={{ display: 'flex', justifyContent: 'space-between' }} mt={2}>
                            <Typography paragraph ml={5} sx={{ fontWeight: 700 }}>
                                {machine.Name}
                            </Typography>
                            <Button variant='outlined' size='small' sx={{ marginRight: 5 }} onClick={() => {
                                handleDeleteMachine(machine)
                            }}>Delete Machine</Button>
                        </Box>
                        <Box>
                            {/* {
                                machine.devices.length !== 0 ?
                                    <DeviceGround machine={machine}></DeviceGround>
                                    : null     we dont need conditional render
                            } */} 
                            <DeviceGround machine ={machine} />

                        </Box>
                    </>
                )
            })}

            <Button variant='contained' size='small' sx={{ marginLeft: 5 }} onClick={handleAddMachine}>Add Machine</Button>


        </Box >
    )
}

export default MachineGround

我在想我应该使用 Redux 吗?或者另一个状态管理那么我该怎么办?我把州搞砸了。

状态管理工具,如 Redux,Context-API 在这里可能是一个不错的选择,但即使您不想使用它们,也可以使用正常的 JavaScript 功能。只需将它们作为 props 从父组件传递给子组件即可。

我会在这里解释我的意思。在你的父组件中编写一个函数,它接受一个机器对象并更新机器数组。现在将此组件作为道具传递给您的子组件。现在,在您的子组件中,使用要添加到机器数组的机器对象调用此函数。繁荣,您在父级中的机器数组将被更新。