Skip to content
Advertisement

How updated object with child component should reflect on parent component

I want to add the macchines in machine array so I defined a specific component with add function in it. So when I add the “process” in “processes” array then it is reflecting on the console using useEffect. But when I add a machine it is reflected in MachineGround Component But not in App component. Overall I am planning to add a dashboard where if even a mcahine is added in machines array it should reflect in the processes in App Component and the dashboard should be updated.

I will appreciate your help.

App component

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

I am thinking that should I use Redux ? or another state management then what should I do? I messed up the states.

Advertisement

Answer

State management tools like Redux, Context-API can be a good option here but even if you do not want to use them, you can make use of normal JavaScript functions. Just pass them as props from your parent component to child component.

I will explain what I mean here. Write a function in your parent component which take a machine object and update the machines array. Now pass this component as props to your child component. Now inside your child component call this function with the machine object that you want to add to your machines array. And boom, your machines array in parent will be updated.

Advertisement