#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?