Home > Enterprise >  how to create new state on the fly
how to create new state on the fly

Time:08-13

I have two components in my project.

One is App.jsx

One is Child.jsx

enter image description here

Right now inside, there are 3 child components was rendered manually. The presenting data in child was passed from parent.

However, in future, I would like to add a button that can create new child on the fly.

let say, I can see a new child 4 appear after child 3, after clicking a new button.

So,

Q1: First question, since presenting data must be from parent (as I dont want to losing data after condition changing from false to true), how could I write things like creating extra state on the fly?

Q2: Second question: How to create a new component after child 3, after clicking a add child button?

For better illustrate, here is my code https://playcode.io/940784

In App.jsx:

import React,{useState,useEffect} from 'react';
import {Child} from './Child.jsx'
export function App(props) {

  [message,setMessage]=useState('');
  [showChild1,setShowChild1]=useState(true);
  [showChild2,setShowChild2]=useState(true);
  [showChild3,setShowChild3]=useState(true);

const [child1data,setChild1data] = useState('child1');
const [child2data,setChild2data] = useState('child2');
const [child3data,setChild3data] = useState('child3');

  useEffect(() => {
    console.log('parent was rendered')
  })
  return (
    <div className='App'>
      

<button >add child</button>
<br/>
<br/>

<button onClick={()=>setShowChild1(!showChild1)}>Show child1</button>
{showChild1 && <Child key='1' data={child1data} setData={setChild1data}/>}
<br/>
<br/>
<button onClick={()=>setShowChild2(!showChild2)}>Show child2</button>
{showChild2 && <Child key='2'data={child2data} setData={setChild2data}/>}

<br/>
<br/>
<button onClick={()=>setShowChild3(!showChild3) } setData={setChild3data}>Show child3</button>
<br/>
{showChild3 && <Child key='3' data={child3data}/>}
      

    </div>
  );
}

// Log to console
console.log('Hello console')

In Child.jsx

import React, {useState, useEffect} from 'react';

export const Child = (props) => {

const {data,setData} = props;



useEffect(()=>{
  console.log(data)
})

  return <>
  
  <h1>This is {data}</h1>
  <input value={data} onChange={((e)=>setData(e.target.value))}></input>
  
  </>
} 

CodePudding user response:

Use data and setData inside Child.jsx, otherwise you can not have infinite childs.

import React, {useState} from 'react';

export const Child = (props) => {

const [data, setData] = useState(props.initialData);


  return <>
  
  <h1>This is {data}</h1>
  <input value={data} onChange={((e)=>setData(e.target.value))}></input>
  
  </>
} 

Now, inside your App.jsx:

    const [childs, setChilds] = useState([]);

return (    

    <button onClick={() => setChilds([...childs, {data: {`child${childs.length}`, showChild: true} }])}>add child</button>

    {
    childs.length &&
    childs.map(child => {
        if(child.showChild){
            return (
                <Child initialData={child.data} />
                <button onClick={() => {let newChildsArray = childs.forEach(item =>{if(item.data === child.data){child.showChild = false}} ) setChilds(newChildsArray)}}>show {child.data}</button>
            )
        }
    }

)

Some of the concepts I used here was Rest Operator, Literal function, and Controlled Component, if you want to search further.

CodePudding user response:

The better approach for this type of problem is not to use separate useState for every child.

But, to use one useState which itself is an array of objects. For this, you can add and manipulate as per your required wish.

  • Related