React列表组件实现异常及TypeScript编译报错求助
问题:React客户端渲染物品列表报错及代码问题
我正在编写一个简单的React客户端,用来向服务器发送消息并接收物品列表,但在实现列表渲染后出现了问题。之前未显式处理响应和Mlist组件时,数据收发正常,现在出现TypeScript报错,同时列表渲染逻辑也有问题。
代码如下
import React, { Component, ReactNode } from "react"; import "./CommentPage.scss"; import axios from 'axios'; import { Message } from "@material-ui/icons"; import { Box } from "@material-ui/core"; export class CommentPage extends Component<any, any> { public render(): ReactNode { return ( <div> <Form /> <Mlist /> </div> ) } } interface message { name: string, value: string } let data: message[] = [{ name: "a", value: "b" }] class Form extends Component<{}, { name: string, message: string }> { constructor(props: {}) { super(props); this.state = { name: '', message: '' }; this.handleChangeName = this.handleChangeName.bind(this); this.handleChangeMess = this.handleChangeMess.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChangeName(event: React.ChangeEvent<HTMLInputElement>) { this.setState({ name: event.target.value, message: this.state.message }); } handleChangeMess(event: React.ChangeEvent<HTMLInputElement>) { this.setState({ name: this.state.name, message: event.target.value }); } handleSubmit(event: React.FormEvent<HTMLFormElement>) { axios.post('http://localhost:8080/addComment', { author: this.state.name, comment: this.state.message }).then(r => { axios.get('http://localhost:8080/allComments').then(r => { r.request.items.map((item: message) => (data.push(item))); }) }).catch(err => { alert(err) }) this.setState({ name: this.state.name, message: '' }); event.preventDefault(); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Name <input type="text" value={this.state.name} onChange={this.handleChangeName} /> Message <input type="text" value={this.state.message} onChange={this.handleChangeMess} /> </label> <input type="submit" value="Submit" /> </form> ); } } class Mlist extends Component<{}, {}> { render() { return ( <p>{data.map((m) => ( <li>{m.name}</li> ))}</p> ); } }
报错信息
TypeScript error in /Users/user/IdeaProjects/namep/front/itmo-hw3/node_modules/@types/babel__traverse/index.d.ts(68,50): ']' expected. TS1005 66 | } 67 | > 68 | export type ArrayKeys<T> = keyof { [P in keyof T as T[P] extends any[] ? P : never]: P }; | ^ 69 | 70 | export class Scope { 71 | constructor(path: NodePath, parentScope?: Scope);
解决方案
1. 解决TypeScript版本报错
这个错误是因为当前使用的TypeScript版本不支持映射类型中的as条件子句(该语法在TypeScript 4.1及以上版本才支持),而@types/babel__traverse依赖了这个语法。
升级TypeScript版本:
# npm npm install typescript@latest --save-dev # yarn yarn add typescript@latest --dev
2. 修正React组件逻辑问题
你的代码存在两个核心问题:全局变量无法触发组件重渲染、axios响应数据获取错误。
修改后的完整代码(采用状态提升,父组件管理列表状态):
import React, { Component, ReactNode } from "react"; import "./CommentPage.scss"; import axios from 'axios'; import { Message } from "@material-ui/icons"; import { Box } from "@material-ui/core"; interface Comment { name: string; value: string; } export class CommentPage extends Component<any, { comments: Comment[] }> { constructor(props: any) { super(props); this.state = { comments: [{ name: "a", value: "b" }] }; this.updateComments = this.updateComments.bind(this); } updateComments(newComments: Comment[]) { this.setState({ comments: newComments }); } public render(): ReactNode { return ( <div> <Form onUpdateComments={this.updateComments} /> <Mlist comments={this.state.comments} /> </div> ) } } class Form extends Component<{ onUpdateComments: (comments: Comment[]) => void }, { name: string, message: string }> { constructor(props: { onUpdateComments: (comments: Comment[]) => void }) { super(props); this.state = { name: '', message: '' }; this.handleChangeName = this.handleChangeName.bind(this); this.handleChangeMess = this.handleChangeMess.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } handleChangeName(event: React.ChangeEvent<HTMLInputElement>) { this.setState({ name: event.target.value, message: this.state.message }); } handleChangeMess(event: React.ChangeEvent<HTMLInputElement>) { this.setState({ name: this.state.name, message: event.target.value }); } handleSubmit(event: React.FormEvent<HTMLFormElement>) { event.preventDefault(); axios.post('http://localhost:8080/addComment', { author: this.state.name, comment: this.state.message }).then(() => { axios.get<Comment[]>('http://localhost:8080/allComments').then(r => { this.props.onUpdateComments(r.data); this.setState({ name: this.state.name, message: '' }); }) }).catch(err => { alert(err.message); }) } render() { return ( <form onSubmit={this.handleSubmit}> <label> Name <input type="text" value={this.state.name} onChange={this.handleChangeName} /> Message <input type="text" value={this.state.message} onChange={this.handleChangeMess} /> </label> <input type="submit" value="Submit" /> </form> ); } } class Mlist extends Component<{ comments: Comment[] }, {}> { render() { return ( <ul> {this.props.comments.map((comment, index) => ( <li key={index}>{comment.name}: {comment.value}</li> ))} </ul> ); } }
关键修改点:
- 把列表数据放到父组件
CommentPage的state中,通过props传递给Mlist组件,状态变化时自动触发重渲染 - 修正axios响应数据获取:用
r.data拿到服务器返回的列表 - 给Form组件传递
onUpdateComments方法,提交成功后更新父组件状态 - 修复HTML语义错误:把包裹li的p标签改成ul
- 循环渲染时添加唯一key属性,符合React要求
内容的提问来源于stack exchange,提问作者student422
相关产品推荐
相关产品推荐

