真的不支持React Hooks的async setState吗?

时间:2019-07-10 17:47:15

标签: javascript reactjs react-hooks

我知道React Hooks不支持异步方法,例如async / await。

仅当setState of the hooks同步并且值成功存储后,我才需要处理下一个过程。

对于原始的this.setState({..}),我使用回调函数执行以下操作,但是我该怎么做hooks setState

例如

export const FirstComponent = () => {
    const [peopleList, setPeopleList] = useState(null)
    const [myList, setMyList] = useState(null)

    const { data, loading, error } = useQuery(gql(GQL_GET_PEOPLE_LIST)

    useEffect(() => {
        const onCompleted = data => {
            setPeopleList(data.list)
       }

       if (!loading) {
          onCompleted(data)
       }
    }, [data, loading, error])

    ...

    const onChangeMyList = id => {
        setMyList(peopleList.filter(x => x.id === id)
          .map(x => x.item.originalList.lists) // <- This must be completed first!!
        openModal(true) // <- Then, it has to be executed!
    }

    ...

    return (
      <div>
        <p onClick={() => onChangeMyList(id)}>Click!</p>
      <div>
    )
}

我应该如何解决?

2 个答案:

答案 0 :(得分:0)

解决这个问题的一种方法是这样的:

const [modalOpen, setModalOpen] = useState(false)
useEffect(() => { if (modalOpen) openModal(true); }, [modalOpen]);

然后不调用openModal(true),而是调用setModalOpen(true);

答案 1 :(得分:0)

在这种情况下,您甚至不需要useEffect()

由于您在更改列表时位于事件处理程序onClick={() => onChangeMyList(id)}中,因此默认情况下,React将自动批处理所有setState()调用更新。这意味着当所有状态都已更新时,将进行下一个渲染。我不知道您如何打开模态,但是您可以执行以下操作:

function App() {

  const [myList, setMyList] = React.useState(['a','b','c']);
  const [openModal, setOpenModal] = React.useState(false);

  function handleClick() {
    setMyList(['a','b','c','d','e','f']);
    setOpenModal(true);
  }

  return(
    <React.Fragment>
      <div><b>myList: </b>{myList}</div>
      <button onClick={handleClick}>Click to change list and open modal</button>
      {openModal &&
        <div><b>I am Modal.</b> I was rendered together with the list: {myList}</div>
      }
    </React.Fragment>
  );
}

ReactDOM.render(<App/>, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"/>