提前为我的问题措辞不当而道歉。
我遵循了一个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(({…}中,将用户和用户名映射到state,然后在下面的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",
"__v": 0
},
{...}
]
在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.Refs:在原始基于类的代码中似乎没有使用该ref,您应该能够删除它。如果确实需要对select
元素的ref,您可以使用useRef
挂钩,文档如下:https://reactjs.org/docs/hooks-reference.html#useref