我目前正在重构我的应用程序以合并 TypeScript,但我在使用 React Router 时遇到了一些问题。我收到以下错误。
类型“{}”中缺少属性“toggleCreateForm”,但在 输入“FormProps”。
据我所知,这是因为我没有将自定义钩子作为道具传递到 Routes 元素中,但我认为我不应该这样做,因为钩子是在另一个组件中声明并由该状态管理的。我需要复制这个似乎违反直觉。
应用程序.tsx
function App(): React.JSX.Element {
const [isLoading, setIsLoading] = useState(false);
const token = useAppSelector(selectToken);
const currentUser = useAppSelector(selectCurrentUser);
const isAuthenticated = useAppSelector(selectAuthenticated);
const dispatch = useAppDispatch();
const checkLoggedIn = useCallback(() => {
setIsLoading(true)
dispatch(userCheckLoggedIn());
setIsLoading(false)
}, [isAuthenticated]);
useEffect(() => {
checkLoggedIn()
}, [checkLoggedIn])
console.debug(
"App",
"currentUser", currentUser,
"token=", token
)
// Find current user using local storage "token"
if (isLoading) {
return <LoadingComponent/>
} else {
if (!(token && isAuthenticated)) {
return (
<div className="">
<NavBar></NavBar>
<Routes>
<Route path="/register" element={<SignupForm/>}/>
<Route path="/" element={<Homepage/>}/>
<Route path="*" element={<Homepage/>}/>
</Routes>
</div>
)
} else {
return (
<div className="App">
<NavBar></NavBar>
<Routes>
<Route path="/workouts" element={<WorkoutList/>}/>
<Route path="/workouts/:workout_id" element={<WorkoutDetail/>}/>
<Route path="/workouts/add" element={<NewWorkoutForm/>}/>
<Route path="/register" element={<SignupForm/>}/>
<Route path="/exercises" element={<ExerciseList/>}/>
<Route path="/exercises/add" element={<NewExerciseForm/>}/>
<Route path="/account" element={<Account/>}/>
<Route path="/" element={<Homepage/>}/>
<Route path="*" element={<NotFound/>}/>
</Routes>
</div>
);
}
}
}
export default App;
NewWorkoutForm.tsx
interface FormValues {
name: string,
category: number
};
interface Category {
id: number,
user_id: number
name: string,
systemdefault: boolean
};
interface FormProps{
toggleCreateForm(): boolean
}
const NewWorkoutForm = ({toggleCreateForm} : FormProps): React.JSX.Element => {
const dispatch = useAppDispatch();
const categories = useAppSelector(selectCategories);
const currentUser = useAppSelector(selectCurrentUser);
const categoryComponents : object[] = categories.map( (cat : Category) => (
<option value={cat.id}>{cat.name}</option>
))
return (
<div className="d-flex justify-content-center">
<Card className="w-25 d-flex flex-column align-items-center pb-3">
<h3>New Workout Form</h3>
<Formik
initialValues={{
name: '',
category: 1,
}}
validate={(values: FormValues) => {
const errors: FormikErrors<FormValues> = {};
if (!values.name){ errors.name = 'Name Required'}
return errors
}}
onSubmit={(values : FormValues, { setSubmitting } : FormikHelpers<FormValues>) => {
setTimeout( async () => {
dispatch(addWorkout({
...values,
user_id: currentUser.id,
favorited: false
}))
setSubmitting(false);
toggleCreateForm();
}, 400)
}}
>
{({isSubmitting}) => (
<div>
<Form>
<div className="d-flex flex-column align-items-center row-gap-3">
<div className="d-flex flex-column align-items-between row-gap-3">
<div className="d-flex flex-row justify-content-between">
<label htmlFor="name">Workout Name:</label>
<Field type='name' name='name'/>
</div>
<div style={{color: "red"}}>
<ErrorMessage name='name' component='div'/>
</div>
<div className="d-flex flex-row justify-content-between">
<label htmlFor="category">Workout Category:</label>
<Field as='select' name='category'>
{categoryComponents}
</Field>
</div>
<div style={{color: "red"}}>
<ErrorMessage name='category' component='div'/>
</div>
</div>
<div className="d-flex flex-row column-gap-5">
<button className="btn btn-danger" onClick={toggleCreateForm}>Cancel</button>
<button className="btn btn-success" type='submit' disabled={isSubmitting}>Create Workout</button>
</div>
</div>
</Form>
</div>
)}
</Formik>
</Card>
</div>
)
}
export default NewWorkoutForm;
toggleCreateForm
是一个自定义钩子,传递到 NewWorkoutForm
const [showCreateWorkoutForm, setShowCreateWorkoutForm] = useToggle();
const toggleCreateForm = () => {
setShowCreateWorkoutForm()
}
这是在 TypeScript 之前工作的。
我认为你只需要编辑你的界面,这样就不需要切换功能了
interface FormProps{
toggleCreateForm?: () => boolean
}