问题描述
提前道歉,没有像我以前说的那样措辞。
我遵循了一个MERN教程,全部使用基于类的React组件完成。我正在尝试将其转换为带有挂钩的功能组件。
我在从初始GET请求中保存用户名/用户名时遇到了麻烦,然后将它们映射到html选择表单上,以便可以将新表单提交归因于现有用户之一。
这是本教程代码的外观,该代码可以按预期运行:
import React,{ Component } from 'react';
import axios from 'axios';
import DatePicker from 'react-datepicker';
import "react-datepicker/dist/react-datepicker.css";
export default class CreateRide extends Component {
constructor(props) {
super(props);
this.onChangeUsername = this.onChangeUsername.bind(this);
this.onChangeDescription = this.onChangeDescription.bind(this);
this.onChangeDuration = this.onChangeDuration.bind(this);
this.onChangeDistance = this.onChangeDistance.bind(this);
this.onChangeDate = this.onChangeDate.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
username: '',description: '',duration: 0,distance: 0,date: new Date(),users: []
}
}
componentDidMount() {
axios.get('http://localhost:5000/users/')
.then(response => {
if (response.data.length > 0) {
this.setState({
users: response.data.map(user => user.username),username: response.data[0].username
});
}
})
.catch((error) => {
console.log(error);
})
}
onChangeUsername(e) {
this.setState({
username: e.target.value
});
}
onChangeDescription(e) {
this.setState({
description: e.target.value
});
}
onChangeDuration(e) {
this.setState({
duration: e.target.value
});
}
onChangeDistance(e) {
this.setState({
distance: e.target.value
});
}
onChangeDate(date) {
this.setState({
date: date
});
}
onSubmit(e) {
e.preventDefault();
const ride = {
username: this.state.username,description: this.state.description,duration: this.state.duration,distance: this.state.distance,date: this.state.date
};
console.log(ride);
axios.post('http://localhost:5000/rides/add',ride)
.then(res => console.log(res.data));
window.location = '/';
}
render() {
return (
<div>
<h3>Create New Ride Log</h3>
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label>Username: </label>
<select ref="userInput"
required
className="form-control"
value={this.state.username}
onChange={this.onChangeUsername}>
{
this.state.users.map(function (user) {
return <option
key={user}
value={user}>{user}
</option>;
})
}
</select>
</div>
<div className="form-group">
<label>Description: </label>
<input type="text"
required
className="form-control"
value={this.state.description}
onChange={this.onChangeDescription}
/>
</div>
<div className="form-group">
<label>Duration (in minutes): </label>
<input
type="text"
className="form-control"
value={this.state.duration}
onChange={this.onChangeDuration}
/>
</div>
<div className="form-group">
<label>Distance (in miles): </label>
<input
type="text"
className="form-control"
value={this.state.distance}
onChange={this.onChangeDistance}
/>
</div>
<div className="form-group">
<label>Date: </label>
<div>
<DatePicker
selected={this.state.date}
onChange={this.onChangeDate}
/>
</div>
</div>
<div className="form-group">
<input type="submit" value="Create Ride Log" className="btn btn-primary" />
</div>
</form>
</div>
)
}
}
我要定位的代码在ComponentDidMount(){...}中,将用户和用户名映射到状态,然后在下面的html呈现器中再次映射。
我现在作为功能组件的外观如下:
import React,{ useState,useEffect } from 'react';
import axios from 'axios';
import DatePicker from 'react-datepicker';
import "react-datepicker/dist/react-datepicker.css";
const CreateRide = (props) => {
const [username,setUsername] = useState('');
const [description,setDescription] = useState('');
const [duration,setDuration] = useState(0);
const [distance,setDistance] = useState(0);
const [date,setDate] = useState(new Date());
const [users,setUsers] = useState([]);
useEffect(() => {
const fetchData = async () => {
const response = await axios.get('http://localhost:5000/users/');
if (response.data.length > 0) {
setUsers({ users: response.data.map(user => user.username ) });
setUsername({ username: response.data[0].username });
}
}
fetchData();
},[]);
const onChangeUsername = (e) => {
setUsername(e.target.value);
}
const onChangeDescription = (e) => {
setDescription(e.target.value);
}
const onChangeDuration = (e) => {
setDuration(e.target.value);
}
const onChangeDistance = (e) => {
setDistance(e.target.value);
}
const onChangeDate = (date) => {
setDate(date);
}
const onSubmit = (e) => {
e.preventDefault();
const ride = {
username: username,description: description,duration: duration,distance: distance,date: date
};
console.log(ride);
axios.post('http://localhost:5000/rides/add',ride)
.then(res => console.log(res.data));
window.location = '/';
}
return (
<div>
<h3>Create New Ride Log</h3>
<form onSubmit={onSubmit}>
<div className="form-group">
<label>Username: </label>
<select
required
className="form-control"
value={username}
onChange={onChangeUsername}>
{
users.map(user => {
return <option key={user} value={user}>{user}</option>;
})
}
</select>
</div>
<div className="form-group">
<label>Description: </label>
<input type="text"
required
className="form-control"
value={description}
onChange={onChangeDescription}
/>
</div>
<div className="form-group">
<label>Duration (in minutes): </label>
<input
type="text"
className="form-control"
value={duration}
onChange={onChangeDuration}
/>
</div>
<div className="form-group">
<label>Distance (in miles): </label>
<input
type="text"
className="form-control"
value={distance}
onChange={onChangeDistance}
/>
</div>
<div className="form-group">
<label>Date: </label>
<div>
<DatePicker
selected={date}
onChange={onChangeDate}
/>
</div>
</div>
<div className="form-group">
<input type="submit" value="Create Ride Log" className="btn btn-primary" />
</div>
</form>
</div>
)
}
export default CreateRide;
这是我通过邮递员运行时的示例json响应的样子:
[
{
"_id": "5f39e38abfa99e273e299fd8","username": "Rudy","createdAt": "2020-08-17T01:55:22.797Z","updatedAt": "2020-08-17T01:55:22.797Z","__v": 0
},{
"_id": "5f39e391bfa99e273e299fd9","username": "James","createdAt": "2020-08-17T01:55:29.727Z","updatedAt": "2020-08-17T01:55:29.727Z",{...}
]
在HTML的下半部分,我正在努力概念化如何在第一个表单组中使用ref ='userInput'。使用功能组件会产生不允许字符串引用的错误。
我知道这包含多个问题,但是我很困惑,任何事情都会受到赞赏。
解决方法
按顺序回答您的问题:
1。用户数据:您正在对象中设置用户数据:
setUsers({ users: response.data.map(user => user.username ) });
setUsername({ username: response.data[0].username });
那应该是:
setUsers(response.data.map(user => user.username));
setUsername(response.data[0].username);
2。参考:看起来您在原始的基于类的代码中使用的不是参考,您应该可以将其删除。如果确实需要引用select
元素,则可以使用useRef
钩子,这里的文档:https://reactjs.org/docs/hooks-reference.html#useref