新道具通过时,更新功能组件状态

时间:2019-06-01 16:07:21

标签: reactjs react-hooks

const {useMemo, useState} = 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 [name, setName] = useState(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>

存在的问题

当我单击<li /><li><button /></li>时,我只会看到父母的名字。

我要实现的目标

当我单击子按钮之一时,我想查看有关子名称的输入值。

1 个答案:

答案 0 :(得分:0)

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
    }