[英]React, passing state setter (useState) to child component with TypeScript
[英]TypeScript Error in React component on useState declaration and passing props to child component
我开始将 TypeScript 与 React 一起使用,目前正在构建一个示例应用程序进行练习,只是从公共 API 获取数据并与 Material UI 一起实现 CRUD,但我在两个组件中遇到错误,因此非常感谢您的帮助。
第一个错误是通过 props 将 function 传递给子组件,第二个错误是使用我为我的数据类型创建的自定义接口声明 useState。
第一个组件是 PostTable.tsx
const PostsTable: React.FunctionComponent = () => {
const [posts, setPosts] = useState<Array<IPost>>([]);
const [selectedPost, setSelectedPost] = useState<IPost | null>(null);
const [dialogOpen, setDialogOpen] = useState<boolean>(false);
const fetchPosts = () => {
PostService.getAllPosts()
.then((response: any) => {
setPosts(response.data);
})
.catch((e: Error) => {
console.log(e);
});
};
useEffect(() => {
fetchPosts();
}, [posts]);
const editPost = (post: IPost) => (event: any) => {
setSelectedPost(post);
setDialogOpen(true);
};
const handleClose = () => {
setDialogOpen(false);
};
const deletePost =
(id: number): any =>
(event: Event) => {
event.stopPropagation();
PostService.deletePost(id)
.then((response: any) => {
setPosts(response.data);
console.log(posts);
})
.catch((e: Error) => {
console.log(e);
});
};
return (
<Container fixed>
{!posts || posts.length < 1 ? (
<div style={{ display: 'flex', justifyContent: 'center' }}>
<CircularProgress color="primary" size={100} />
</div>
) : (
<TableContainer component={Paper}>
<Table sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell align="left">User Id</TableCell>
<TableCell align="left">Post Id</TableCell>
<TableCell align="left">Title</TableCell>
<TableCell align="left">Actions</TableCell>
</TableRow>
</TableHead>
<TableBody>
{posts.map((post: IPost) => (
<TableRow
key={post.id}
sx={{ '&:last-child td, &:last-child th': { border: 0 } }}
>
<TableCell>{post.userId}</TableCell>
<TableCell align="left">{post.id}</TableCell>
<TableCell align="left">{post.title}</TableCell>
<TableCell align="left">
<Tooltip title="Delete">
<IconButton onClick={editPost(post)}>
<EditIcon />
</IconButton>
</Tooltip>
<Tooltip title="Edit">
<IconButton onClick={deletePost(post.id)}>
<DeleteIcon />
</IconButton>
</Tooltip>
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
)}
{
<EditPostDialog
open={dialogOpen}
handleClose={handleClose}
/**Error is on this line**/
selectedPost={selectedPost}
/>
}
</Container>
);
};
其次,子 EditPostDialog.ts
const EditPostDialog: React.FunctionComponent<IEditPostDialog> = (
props: IEditPostDialog
) => {
const { open, handleClose, selectedPost } = props;
/**Error on this line**/
const [post, setPost] = useState<IPost>({});
useEffect(() => {
const newPost = {
id: selectedPost.id,
userId: selectedPost.userId,
title: selectedPost.title,
body: selectedPost.body,
};
setPost(newPost);
}, [selectedPost]);
const handleChange = (event: any) => {
setPost({ ...post, [event.target.name]: event.target.value });
};
const handleSubmit = () => {
PostService.updatePost(post.id, post);
handleClose();
};
return (
<Dialog onClose={handleClose} open={open}>
<DialogTitle id="simple-dialog-title">Post info</DialogTitle>
<DialogContent classes={{ root: 'dialog-content' }}>
<TextField
id="id"
label="Post Id"
name="id"
variant="outlined"
value={post.id}
onChange={handleChange}
/>
<TextField
id="userId"
label="User Id"
name="userId"
variant="outlined"
value={post.userId}
onChange={handleChange}
/>
<TextField
id="title"
label="Title"
name="title"
variant="outlined"
value={post.title}
onChange={handleChange}
/>
<TextField
id="body"
label="Body"
name="body"
variant="outlined"
value={post.body}
onChange={handleChange}
/>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Close</Button>
<Button onClick={handleSubmit}>Submit</Button>
</DialogActions>
</Dialog>
);
};
您可能需要 IPost 接口,所以它是:
export default interface IPost {
userId: number;
id: number;
title: string;
body: string;
}
最后是 IEditPost 界面:
export default interface IEditPostDialog {
open: boolean;
handleClose: () => void;
selectedPost: IPost;
}
提前谢谢大家!
第二个错误基本上是您使用空的 object 初始化 IPost 类型的IPost
。 但是界面希望您的所有属性都存在。 您可以通过附加?
在物业名称之后。
您可以简化您的子组件来解决这个问题:
const [post, setPost] = useState<IPost>(selectedPost);
useEffect(() => {
setPost(selectedPost);
}, [selectedPost]);
如果您遇到其他问题:首先,您不需要明确指定null
:
// Your code: const [selectedPost, setSelectedPost] = useState<IPost | null>(null);
const [selectedPost, setSelectedPost] = useState<IPost>(null); // should work perfectly fine
我们需要查看接口IEditPostDialog
以了解将值selectedPost
传递给底层组件的问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.