使用useState通过单击按钮来反应更新状态

时间:2019-04-16 06:55:02

标签: reactjs react-hooks

任何人都可以向我解释解决以下问题的“正确”方法是什么。我有一个简单的页面,其中包含事件数据。最初,这是上周的数据,但是页面上有一个按钮,可将所有数据设置为全部。我使用useEffect()将loadData()设置为初始值all = false。当我单击按钮时,我要全部更新为true,将数据更新为所有数据。

下面的代码可以工作,但是有点奇怪,因为我首先必须获取!all的数据,然后设置all = true,但随后又重新渲染。

有没有很好的方法可以做到这一点?我尝试以另一种方式放置“ onClick”代码,因此:setAll(!all); loadData(all),但这不起作用,因为状态不会立即更新。

任何帮助/提示都很棒!

 const Events = ({auth}) => {


const [data, setEventData] = useState([])
const [all, setAll] = useState(false)

const loadData = async (givenScope) => {
    const scope = (givenScope ? '' : '?scope=last_week')
    const eventdata = await makeAPICall('/api/events' + scope, 'GET', null, await auth.getAccessToken())
    setEventData(eventdata);
}

useEffect(() => {
    loadData(all);
}, [])

const columns = [{
    Header: 'Datum/tijd',
    accessor: 'datetime',
    Cell: props => <Moment date={props.value} tz="Europe/Amsterdam" format="YYYY-MM-DD HH:mm"/>
}, {
    Header: 'Event',
    accessor: 'value',
}]        

return <div><Button onClick={() => {loadData(!all);setAll(!all)}}>{all ? 'Last week' : 'All'}</Button> <DefaultTable data={data} columns={columns} loading={data.length > 0 ? false : true} /></div>

}

2 个答案:

答案 0 :(得分:2)

处理上述代码的一种相对简单的方法是将all作为值传递给useEffect的依赖项数组,这样您就不必担心loadData在状态更新后被执行< / p>

const Events = ({auth}) => {

    const [data, setEventData] = useState([])
    const [all, setAll] = useState(false)

    const loadData = async (givenScope) => {
        const scope = (givenScope ? '' : '?scope=last_week')
        const eventdata = await makeAPICall('/api/events' + scope, 'GET', null, await auth.getAccessToken())
        setEventData(eventdata);
    }

    useEffect(() => {
        loadData(all);
    }, [all])

    const columns = [{
        Header: 'Datum/tijd',
        accessor: 'datetime',
        Cell: props => <Moment date={props.value} tz="Europe/Amsterdam" format="YYYY-MM-DD HH:mm"/>
    }, {
        Header: 'Event',
        accessor: 'value',
    }]        

    return <div><Button onClick={() => {setAll(all => !all)}}>{all ? 'Last week' : 'All'}</Button> <DefaultTable data={data} columns={columns} loading={data.length > 0 ? false : true} /></div>

}

在任何情况下,由于数据都是异步可用的,因此您的代码将呈现两次。为了改善用户体验,您可以在获取数据时显示加载程序。

答案 1 :(得分:0)

您可以在按钮的onClick上尝试以下操作:

<Button 
  onClick={ () => {
    setAll((prevState) => {
      loadData(!prevState);    // This will load the data during the state update
      return !prevState;
    }
  }}
/>