Хук UseState не обновляет шаг должным образом - PullRequest
0 голосов
/ 02 февраля 2020

Я хочу изменить значение состояния с изменением в элементе ' select '. Поэтому я вызываю метод setFilter в обработчике onChange. Но состояние не обновляется. Он держит предыдущее значение. Как решить эту проблему?

Я хочу изменить значение состояния с изменением в элементе ' select '. Поэтому я вызываю метод setFilter в обработчике onChange. Но состояние не обновляется. Он держит предыдущее значение. Как решить эту проблему?

<code>import React, { useState, useEffect } from 'react'
import { useHistory } from 'react-router-dom'
import { useApolloClient} from 'react-apollo';
import { Formik, Form, ErrorMessage } from 'formik';
import * as Yup from "yup";

import AsyncPaginate from 'react-select-async-paginate'
import { GET_ITEM_CODES } from '../../library/Query';


export default function SampleForm({initialData}){
const history = useHistory();

const [productFilter, setProductFilter] = useState('');

const client = useApolloClient();

const defaultAdditional = {
    cursor : null
}
const shouldLoadMore = (scrollHeight, clientHeight, scrollTop) => {
    const bottomBorder = (scrollHeight - clientHeight) / 2
     return bottomBorder < scrollTop
}
const loadItemcodeOptions = async (q = 0, prevOptions, {cursor}) => {
    console.log('qu',q*1)
    const options = [];
    console.log('load')
    const response = await client.query({
        query:GET_ITEM_CODES,
        variables : {filter: {
            number_gte : q*1
        },skip:0, first:4, after: cursor}
    })

    console.log('res',response)
    response.data.itemCodes.itemCodes.map(item => {
        return options.push({
            value: item.number,
            label: `${item.number} ${item.description}`
        })
    })
    console.log('0',options)

    return {
        options,
        hasMore: response.data.itemCodes.hasMore,
        additional: {
            cursor: response.data.itemCodes.cursor.toString()
        }
    }
}

const handleFilter = (e) => {
    console.log('e',e)
    setProductFilter(e.value)
    console.log('pf',productFilter) // output is previous State(wrong)
}

useEffect(() => {
    console.log('epf',productFilter) // output the current state(expected)
})

return(
    <Formik
       initialValues = {{
           itemCode: !!initialData ? {value: initialData.itemCode, label: initialData.itemCode} : '',
       }}

       validationSchema = {Yup.object().shape({
           itemCode: Yup.number().required('Required'),
       })}
    >
        {({values, isSubmitting, setFieldValue, touched, errors }) => (
            <Form>
                <label htmlFor="itemCode">Item Code</label>
                <AsyncPaginate
                    name="itemCode"
                    defaultOptions
                    debounceTimeout={300}
                    cacheOptions
                    additional={defaultAdditional}
                    value={values.itemCode}
                    loadOptions={loadItemcodeOptions}
                    onChange={option => {
                        handleFilter(option)
                        setFieldValue('itemCode', option)
                    }}
                    shouldLoadMore={shouldLoadMore}
                />
                <ErrorMessage name="itemcode"/>
                <pre>{JSON.stringify(values, null, 2)}
)} )}

1 Ответ

0 голосов
/ 02 февраля 2020

На самом деле setProductFilter устанавливает состояние асинхронно, поэтому вы получите обновленное состояние в эффекте, а не сразу после вызова setState. Но ваш эффект будет запускаться каждый раз, когда ваш компонент будет перерисован, поэтому вы должны добавить productFilter как зависимость useEffect. Еще одна вещь, которую я хочу упомянуть, это то, что я не знаю о вашем случае использования, но вы должны придерживаться правила: Единственный источник правды . У вас есть два состояния для productFilter: одно в Formik, т.е. itemCode, а другое в вашем локальном состоянии. Я думаю, что вы можете удалить свое местное состояние и использовать код элемента из formikProps.values.itemCode.

...