I have two components in my project.
One is App.jsx
One is Child.jsx
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.