Обратный вызов компонента, потребляющий React Typesscript

#reactjs #typescript #callback

#reactjs #typescript #обратный вызов

Вопрос:

Как я могу использовать метод обратного вызова?

Это вызов компонента:

 //This is the Parent Component
const [selectedDateState, setSelectedDateState] = React.useState();
...
<DateSelection initDate={new Date()} label={"Pick a date"} onValueChange={setSelectedDateState}/>
                                                         {/*^^^^^^^^^^^^ Error */}
 

Я получаю сообщение об ошибке:

 TS2322: Type 'Dispatch<SetStateAction<undefined>>' 
is not assignable to type '(newDate: Date) => void'.   
Types of parameters 'value' and 'newDate' are incompatible.     
Type 'Date' is not assignable to type 'SetStateAction<undefined>'.       
Type 'Date' provides no match for the signature '(prevState: undefined): undefined'.
 

Это компонент, простой инструмент выбора даты.
Когда я вызываю его, я передаю сегодняшнюю дату и метку.
Если дата изменена, дата должна быть установлена в состоянии на родительской странице.

DateSelection.tsx

 import 'date-fns';
import React, {useEffect} from 'react';
import Grid from '@material-ui/core/Grid';
import DateFnsUtils from '@date-io/date-fns';
import {
    MuiPickersUtilsProvider,
    KeyboardDatePicker,
} from '@material-ui/pickers';

type ChildProps = {
    initDate: Date, 
    label: string,
    onValueChange: (newDate: Date) => void;
}

export default function DateSelection({initDate, label, onValueChange}: ChildProps) {
    // The first commit of Material-UI
    const [selectedDate, setSelectedDate] = React.useState<Date>();

    const handleDateChange = (date: Date | null) => {
        if (date) {
            setSelectedDate(date);
            onValueChange(date);
        }
    };

    useEffect(() => {
        setSelectedDate(initDate);
    }, [])

    return (
        <MuiPickersUtilsProvider utils={DateFnsUtils}>
            <Grid container justify="space-around">
                <KeyboardDatePicker
                    margin="normal"
                    id="date-picker-dialog"
                    label= {label}
                    format="dd.MM.yyyy"
                    value={selectedDate}
                    onChange={handleDateChange}
                    KeyboardButtonProps={{
                        'aria-label': 'change date',
                    }}
                />
            </Grid>
        </MuiPickersUtilsProvider>
    );
}
 

Ответ №1:

Это потому setSelectedDateState , что from React.useState имеет сигнатуру типа: Dispatch<SetStateAction<undefined>> и вы определили тип для onValueChange as (newDate: Date) => void .

Таким образом, вы можете либо изменить тип на onValueChange быть Dispatch<SetStateAction<Date>> , где типы Dispatch и SetStateAction происходят из реакции…

 import * as React from "react";

type DateSelectionProps = {
   ...
   onValueChange: React.Dispatch<React.SetStateAction<Date>>;
}

 

Или измените компонент на следующий, чтобы соответствовать сигнатуре типа, для которой вы определили onValueChange :

 const [selectedDateState, setSelectedDateState] = React.useState<Date>();
...
<DateSelection initDate={new Date()} label={"Pick a date"} onValueChange={(date) => setSelectedDateState(date)}/>
 

Ответ №2:

Извините

Я нашел решение. Я должен использовать useCallback вместо useState в родительском компоненте!

     const handleSelectedDate = useCallback((e)=>{
        console.log(e);
        setSelectedDateState( e );
    },[]);

...

 <DateSelection initDate={new Date()} label={"Pick a date"} onValueChange={ handleSelectedDate }/>
 

Комментарии:

1. ах, это тоже сработало бы так. Спасибо за ваш ответ. Какой вариант вы бы порекомендовали onValueChange = {(date) => setSelectedDateState (дата)} или useCallback?