const {useMemo, useState, useRef} = React
const DATA = {
1:{name: 'John', children: ['Smith','Mary','Chris']},
2:{name:'Ama', children: ['Natalia','Obama']}
};
const List = ()=>{
const generateList = useMemo(() => {
let arr = [];
for (let i in DATA) {
arr.push(<Item key={i} id={i} {...DATA[i]} /> );
}
return arr;
}, [DATA])
return (
<ul>{generateList}</ul>
);
}
const Item = (props) =>{
const [isShow, setIsShow] = useState(false);
const [name, setName] = useState(props.name);
const toggle = () => setIsShow(!isShow)
const handleClick = (e,name) => {
e.stopPropagation();
setName(name);
toggle();
}
return(
<React.Fragment>
<li onClick={toggle}>
<p>{props.name}</p>
{props.children.map((i,j)=>(<button key={j} onClick={(e)=>handleClick(e,i)} >{i}</button>))}
</li>
<Modal visible={isShow} toggle={toggle} name={name}/>
</React.Fragment>
);
}
const Modal = (props) => {
const prevName = useRef(props.name);
const [name, setName] = useState(props.name);
if(prevName.current !== props.name){
prevName.current=name;
setName(props.name)
};
return props.visible ? ReactDOM.createPortal(
<React.Fragment>
<div className="dimmer"/>
<div className="modal">
<input type="text" value={name} onChange={(e)=>setName(e.target.value)} />
<button onClick={props.toggle}>close</button>
</div>
</React.Fragment>, document.getElementById("modal")
) : null
}
ReactDOM.render(
<List/>,document.getElementById('root')
)
.dimmer{
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-color: rgba(0,0,0,0.16);
}
.modal{
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
background-color: white;
width: 200px;
height: 120px;
}
li:hover{ background-color: #f0f0f0; cursor: pointer; }
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
<div id="modal"></div>
Я решил, используя useRef()
.
const Modal = (props) => {
const prevName = useRef(props.name);
const [name, setName] = useState(props.name);
if(prevName.current !== props.name){
prevName.current=name;
setName(props.name)
};
return props.visible ? ReactDOM.createPortal(
<React.Fragment>
<div className="dimmer"/>
<div className="modal">
<input type="text" value={name} onChange={(e)=>setName(e.target.value)} />
<button onClick={props.toggle}>close</button>
</div>
</React.Fragment>, document.getElementById("modal")
) : null
}