I have application, which fetches data from the server, which is written in nodeJS.
Using componentDidMount i fetch the data. On page is input for name a table with data and every row has checkbox. When I click on button 'send', selected rows are send on backend. On backend I validate unique name. If is not, I return error. But fronted is every time refreshed. And is not possible get error message.
import React, {Component} from 'react';
import axios from 'axios';
import MyNavbar from "./MyNavbar";
class Offer extends Component {
constructor(props) {
super(props);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleCheckedOrder = this.handleCheckedOrder.bind(this);
this.state = {
offers: [],
name: '',
selectedFoods: [],
selectedBuild: 'Nevybráno',
isOrderChecked: false
};
}
componentDidMount() {
this.getOffer();
}
getOffer() {
const url = '/offer';
axios.get(url).then(response => {
this.setState({offers: response.data})
}).catch(() => 'Cannot load menu');
};
handleNameChange = evt => {
this.setState({name: evt.target.value});
};
handleChecboxChange = offer => {
if (this.state.selectedFoods.includes(offer)) {
this.setState({selectedFoods: this.state.selectedFoods.filter(item => item !== offer)});
} else {
this.setState({selectedFoods: [...this.state.selectedFoods, offer]});
}
};
handleCheckedOrder() {
this.setState({isChecked: !this.state.isChecked});
}
isValid() {
let isEnabledSubmit = this.state.name.length > 0;
let isSelectedFoodAndNotOnlySoap = this.state.selectedFoods.length > 0 && this.state.selectedFoods.some(food => food.index !== 0);
let isSelectedBuild = this.state.selectedBuild !== 'Nevybráno';
return isEnabledSubmit && isSelectedFoodAndNotOnlySoap && isSelectedBuild;
}
handleSubmit() {
axios({
method: 'post',
url: '/order',
headers: {},
data: {
name: this.state.name,
food: this.state.selectedFoods,
order: this.state.isChecked,
build: this.state.selectedBuild
}
});
};
render() {
const {offers} = this.state;
const options = ["Nevybráno", "A", "B"];
return (
<div>
<MyNavbar/>
<div className="container">
<form className="form-inline justify-content-center" onSubmit={this.handleSubmit}>
<table className="table">
<tbody>
<tr>
<th> </th>
<th>#</th>
<th>Váha</th>
<th>Menu</th>
<th>Cena</th>
</tr>
{offers.map((offer) => {
return (
<tr key={offer.index}>
<td style={{width: '5%'}}>
<input type="checkbox" className="checkbox"
onChange={this.handleChecboxChange.bind(this, offer)}/>
</td>
<td style={{width: '5%'}}>{offer.index}</td>
<td style={{width: '10%'}}>{offer.weight}g</td>
<td style={{width: '70%'}}>{offer.name}</td>
<td style={{width: '20%'}}>{offer.discount} Kč</td>
</tr>
)
})}
</tbody>
</table>
<label className="sr-only" htmlFor="inlineFormInput">Name</label>
<input type="text" className="form-control mb-2 mr-sm-2 mb-sm-0" id="inlineFormInput"
placeholder="Jméno" onChange={this.handleNameChange}/>
<label className="mr-sm-2" htmlFor="inlineFormCustomSelect">Budova</label>
<select className="custom-select mb-2 mr-sm-2 mb-sm-0" id="inlineFormCustomSelect"
onChange={(e) => this.setState({selectedBuild: e.target.value})}>
{options.map(option => {
return <option value={option} key={option}>{option}</option>
})}
</select>
<div className="form-check mb-2 mr-sm-2 mb-sm-0">
<label className="form-check-label">
<input className="form-check-input" type="checkbox"
onChange={this.handleCheckedOrder}/> Objednám
</label>
</div>
<button type="submit" className="btn btn-secondary"
disabled={!this.isValid()}>Odeslat
</button>
</form>
</div>
</div>
);
}
}
export default Offer;
This is because the button submits the form and refreshes the page by default. This can be prevented by using evt.preventDefault();
handleSubmit(evt) {
evt.preventDefault();
axios({
method: 'post',
url: '/order',
headers: {},
data: {
name: this.state.name,
food: this.state.selectedFoods,
order: this.state.isChecked,
build: this.state.selectedBuild
}
});
};
In addition to what maartendev's comment, to get the errors and result in component state you can write the handler as:
handleSubmit(evt) {
evt.preventDefault();
axios({
method: 'post',
url: '/order',
headers: {},
data: {
name: this.state.name,
food: this.state.selectedFoods,
order: this.state.isChecked,
build: this.state.selectedBuild
}
}).catch(({ response }) => this.setState({ errors: response.data }));
}
This will give you errors in this.state.errors which can be used in render method.
Try to add it in the form submit function evt.preventDefault();}
handleSubmit=(eve)=>
{
evt.preventDefault();
}
Tell me if it works or not.
Related
I have listing view working correctly and I want to pass data to update view by Id - in URL Id is passed correctly, but without data saved to this Id. In console log id is tagged as undefined
UpdateCar.jsx
import React, { Component } from 'react';
import CarServices from '../../Services/CarServices';
class UpdateCar extends Component {
constructor(props) {
super(props)
this.state = {
carId: this.props.match.id,
brand: '',
color: ''
}
this.changeBrandHandler = this.changeBrandHandler.bind(this);
this.changeColorHandler = this.changeColorHandler.bind(this);
this.getCarId = this.getCarId.bind(this);
this.updateCar = this.updateCar.bind(this);
}
componentDidMount() {
CarServices.getCarById(this.state.carId).then((res) => {
let car = res.data;
this.setState({
brand: car.brand,
color: car.color
});
});
}
changeBrandHandler = (event) => {
this.setState({ brand: event.target.value });
}
changeColorHandler = (event) => {
this.setState({ color: event.target.value });
}
updateCar = (e) => {
e.preventDefault();
let car = { brand: this.state.brand, color: this.state.color };
console.log('test: ' + JSON.stringify(car));
console.log('id => ' + JSON.stringify(car.carId));
}
cancel() {
this.props.history.push('/showCars');
}
render() {
return (
<div>
<div className='container'>
<div className='row'>
<div className='card col-md-6 offset-md-3 offset-md-3'>
<h3 className='text-center'> Edit car </h3>
<div className='cardBody'>
<form>
<div className='form-group'>
<label> Brand: </label>
<input placeholder="brand" name="brand" className="form-control"
value={this.state.brand} onChange={this.changeBrandHandler} />
<label> Color: </label>
<input placeholder="color" name="color" className="form-control"
value={this.state.color} onChange={this.changeColorHandler} />
</div>
<button className="btn btn-success" onClick={this.updateCar}>Save</button>
<button className="btn btn-danger" onClick={this.cancel.bind(this)} style={{ marginLeft: "10px" }}>Cancel</button>
</form>
</div>
</div>
</div>
</div>
</div>
);
}
}
export default UpdateCar;
CarServices.js
When I hardcode id in url it works correclty - I don't know why I don't have any data from database in placeholders
import axios from 'axios';
const CAR_API_BASE_URI = "http://localhost:8080/car"
class CarServices{
getCars(){
return axios.get(CAR_API_BASE_URI);
}
addCar(car){
return axios.post(CAR_API_BASE_URI, car);
}
getCarById(id){
return axios.get(CAR_API_BASE_URI + '/' + id);
//return axios.get("http://localhost:8080/car/2"); - correclty view data from database saved with id:2
}
}
export default new CarServices();
ListCar.jsx
import React, { Component } from 'react';
import CarServices from '../../Services/CarServices';
class ListCar extends Component {
constructor(props){
super(props)
this.state = {
cars: []
}
this.addCar = this.addCar.bind(this);
this.editCar = this.editCar.bind(this);
}
addCar(){
this.props.history.push('/addCar');
}
editCar(id){
this.props.history.push(`/editCar/${id}`);
}
componentDidMount(){
CarServices.getCars().then((res)=>{
this.setState({ cars: res.data})
})
}
render() {
return (
<div>
<h2 className='text-center'>Car list </h2>
<div className='row'>
<button className='btn btn-primary' onClick={this.addCar} style={{marginLeft: "15px"}} >Add car</button>
</div>
<div className='row'></div>
<table className='table table-striped table-bordered'>
<thead>
<tr>
<th className='text-center'>Id</th>
<th className='text-center'>brand</th>
<th className='text-center'>color</th>
<th className='text-center'>action</th>
</tr>
</thead>
<tbody>
{
this.state.cars.map(
car =>
<tr key = {car.carId}>
<td className='text-center'>{car.carId}</td>
<td className='text-center'>{car.brand}</td>
<td className='text-center'>{car.color}</td>
<td className='text-center'>
<button onClick ={ () => this.editCar(car.carId)} className="btn btn-info">Update </button>
<button style={{marginLeft: "10px"}} className="btn btn-danger">Delete </button>
<button style={{marginLeft: "10px"}} className="btn btn-info">View </button>
</td>
</tr>
)}
</tbody>
</table>
</div>
);
}
}
export default ListCar;
Assuming the UpdateCar component is correctly rendered on a Route and receives the route props, the issue is likely that this.props.match.id won't necessarily be defined in the constructor when the component is mounting.
If you must reference props in the constructor then reference the passed props argument.
constructor(props) { // <-- reference this props
super(props)
this.state = {
carId: props.match.id, // reference props arg
brand: '',
color: ''
}
...
}
It's better to reference props directly though as it's considered anti-pattern in React to store props into local state.
componentDidMount() {
const { match } = this.props;
if (match.id) {
CarServices.getCarById(match.id)
.then((res) => {
const { brand, color } = res.data;
this.setState({ brand, color });
})
.catch(error => {
// catch and handle any Promise rejections or thrown errors
});
}
}
Don't forget to also handle the id route path parameter changing while the UpdateCar component is mounted.
componentDidUpdate(prevProps) {
const { match } = this.props;
if (prevProps.match.id !== match.id) {
CarServices.getCarById(match.id)
.then((res) => {
const { brand, color } = res.data;
this.setState({ brand, color });
})
.catch(error => {
// catch and handle any Promise rejections or thrown errors
});
}
}
I have a friend form that has a button to add friend via ajax call (addNewFriendClick). Once added it should output the id and then using that id the same button (onClickUpdate) should allow to update by grabbing that id.
After adding and clicking a second time to update the friend I get the error below in my console.
The website below should have the /id as the url ending endpoint but i am getting
"[object%20Object]"
PUT https://api.remotebootcamp.dev/api/friends/[object%20Object] 404 (Not Found)
Below is my Routes
<Route path="/friends/*" element={<AddFriend></AddFriend>}>
<Route path=":personId" element={<AddFriend />}></Route>
<Route path="new" element={<AddFriend />}></Route>
</Route>
import React, { useState, useEffect } from "react";
import * as friendService from "../../services/friendService";
import toastr from "toastr";
import { useParams, useNavigate, useLocation } from "react-router-dom";
function AddFriend() {
const [userFormData, setUserFormData] = useState({
title: "",
bio: "",
summary: "",
headline: "",
slug: "",
statusId: "",
primaryImage: "",
});
// useEffect to grab url
const navigate = useNavigate();
const { state } = useLocation();
const friendId = useParams();
const [peepId, setPeepId] = useState(friendId);
console.log({ userFormData, peepId, state }, "param and navigate");
useEffect(() => {
console.log("useEffect firing");
setPeepId(friendId);
if (state) {
setUserFormData((prevState) => {
console.log(state);
return { ...prevState, ...state.payload };
});
}
}, [friendId, state]);
const onFormFieldChange = (event) => {
const target = event.target;
const value = target.value;
console.log("VALUE ->", value);
const name = target.name;
console.log("NAME ->", name);
setUserFormData((prevState) => {
console.log("updater onChange");
const updatedFormData = {
...prevState,
};
updatedFormData[name] = value;
return updatedFormData;
});
};
useEffect(() => {
console.log("useEffect firing");
setPeepId(friendId);
if (state) {
setUserFormData((prevState) => {
console.log(state);
return { ...prevState, ...state.payload };
});
}
}, [friendId, state]);
const addNewFriendClick = (event) => {
event.preventDefault();
console.log(userFormData, "inside addNewFriendClick")
console.log("on Click", { syntheticEvent: event });
friendService.addFriend(userFormData).then(onSuccessAdd).catch(onErrAdd);
};
const onSuccessAdd = (response) => {
console.log(response, "onSuccessAdd response");
// console.log(response.data.item, "onSuccessAdd response.data.item");
setNewFriendInformation(response);
console.log(response,"onSuccessAdd after setNewFriend" )
friendService.getFriendById(response).then(onSuccessGet).catch(onErrorGet);
toastr.success("Congratulations! You have successfully added a friend!");
};
const onErrAdd = (err) => {
console.log("ping err", err);
// swal("Error Registering");
toastr.error(
"Error adding a new friend. Please check if all fields are correct"
);
};
const onClickUpdate = (event) => {
console.log(userFormData, "userFormData inside click Edit");
event.preventDefault();
friendService
.updateFriend(userFormData)
.then(onSuccessUpdate)
.catch(onErrorUpdate);
};
const onSuccessUpdate = (response) => {
console.log(response);
toastr.success("Congratulations! You have successfully updated a friend!");
navigate("/friends");
};
const onErrorUpdate = (error) => {
console.log(error, "inside error update");
toastr.error(
"Error updating friend. Please check all fields are correct and that user being updated is valid"
);
};
const setNewFriendInformation = (id) => {
setUserFormData((prevState) => {
let newState = { ...prevState };
newState.id = id;
return newState;
});
};
const onSuccessGet = (response) => {
console.log(response);
navigate();
};
const onErrorGet = (error) => {
console.log(error);
console.log("inside getById error form");
};
// const updateFriend()
return (
<React.Fragment>
<h1 className="container">Add New</h1>
<hr />
<main role="main">
<div className="container col-6 mt-5 fs-2">
<div className="row">
<div className="col-md-5">
<form>
<div className="mb-3">
<label htmlFor="title" className="form-label">
Title
</label>
<input
type="text"
className="form-control form-control-lg"
id="title"
name="title"
placeholder="Please The Enter Title"
onChange={onFormFieldChange}
value={userFormData.title}
/>
</div>
<div className="mb-3">
<label htmlFor="bio" className="form-label">
Bio
</label>
<input
type="text"
className="form-control form-control-lg"
id="bio"
name="bio"
placeholder="Please Enter The Bio"
value={userFormData.bio}
onChange={onFormFieldChange}
/>
</div>
<div className="mb-3">
<label htmlFor="summary" className="form-label">
Summary
</label>
<input
type="text"
className="form-control form-control-lg"
id="summary"
name="summary"
placeholder="Please Enter The Summary"
onChange={onFormFieldChange}
value={userFormData.summary}
/>
</div>
<div className="mb-3">
<label htmlFor="headline" className="form-label">
Headline
</label>
<input
type="text"
className="form-control form-control-lg"
id="headline"
name="headline"
placeholder="Please Enter The Headline"
onChange={onFormFieldChange}
value={userFormData.headline}
/>
</div>
<div className="mb-3">
<label htmlFor="slug" className="form-label">
Slug
</label>
<input
type="text"
className="form-control form-control-lg"
id="slug"
name="slug"
placeholder="Please The Slug"
onChange={onFormFieldChange}
value={userFormData.slug}
/>
</div>
<div className="mb-3">
<label htmlFor="statusId" className="form-label">
Status Id
</label>
<select
type="select"
className="form-control"
id="statusId"
name="statusId"
placeholder="Please Enter Status ID"
onChange={onFormFieldChange}
value={userFormData.statusId}
>
<option>Default</option>
<option value="Active">Active</option>
<option value="NotSet">NotSet</option>
<option value="Deleted">Deleted</option>
<option value="Flagged">Flagged</option>
</select>
</div>
<div className="mb-3">
<label htmlFor="primaryImage" className="form-label">
Primary Image Url
</label>
<input
type="text"
className="form-control form-control-lg"
id="primaryImage"
name="primaryImage"
placeholder="Please Enter The Primary Image"
onChange={onFormFieldChange}
value={userFormData.primaryImage}
/>
</div>
{userFormData.id ? (
<button
onClick={onClickUpdate}
type="sumbit"
className="btn btn-primary"
>
Update Friend
</button>
) : (
<button
onClick={addNewFriendClick}
type="sumbit"
className="btn btn-primary"
>
Add Friend
</button>
)}
</form>
</div>
</div>
</div>
<div className="col-md-5">
<h5>Output</h5>
<pre>
<code>{JSON.stringify(userFormData, undefined, 2)}</code>
</pre>
</div>
</main>
</React.Fragment>
);
}
export default AddFriend;
import axios from "axios";
import * as helper from "./serviceHelper";
let getFriend = () => {
const config = {
method: "GET",
url: "https://api.remotebootcamp.dev/api/friends?pageIndex=0&pageSize=10",
withCredentials: true,
crossdomain: true,
headers: { "Content-Type": "application/json" },
};
return axios(config).then(helper.onGlobalSuccess);
//we use data as the param for success handler
};
let addFriend = (payload) => {
const config = {
method: "POST",
url: "https://api.remotebootcamp.dev/api/friends",
data: payload,
withCredentials: true,
crossdomain: true,
headers: { "Content-Type": "application/json" },
};
return axios(config).then(response => {
console.log(response, "inside service addfriend return")
return response.data.item;
});
}
let updateFriend = (id, payload) => {
console.log(id, payload, "from updateFriendservice");
const config = {
method: "PUT",
data: (id, payload),
url: `https://api.remotebootcamp.dev/api/friends/${id}`,
withCredentials: true,
crossdomain: true,
headers: { "Content-Type": "application/json" },
};
return axios(config);
};
let deleteFriend = (id) => {
console.log(id);
const config = {
method: "DELETE",
// data: id,
url: `https://api.remotebootcamp.dev/api/friends/${id}`,
withCredentials: true,
crossdomain: true,
headers: { "Content-Type": "application/json" },
};
return axios(config);
};
let getFriendById = (id, payload) =>{
console.log(id, payload, "inside getFriend friedService")
const config = {
method: "PUT",
data: (id, payload),
url: `https://api.remotebootcamp.dev/api/friends/${id}`,
withCredentials: true,
crossdomain: true,
headers: { "Content-Type": "application/json" },
}
return axios(config);
}
export { getFriend, addFriend, deleteFriend, updateFriend, getFriendById };
Maybe you should get friendId as following
const { personId: friendId } = useParams();
Also you need to send two prams to friendService.updateFriend() but sent only one param.
Here is the code:
import React from 'react';
class EditEntry extends React.Component {
constructor(props) {
super(props);
this.state = {
entry: '',
description: '',
item: [],
error: null
};
this.handleChangeEntry = this.handleChangeEntry.bind(this);
this.handleChangeDescription = this.handleChangeDescription.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
componentDidMount() {
const { match: { params } } = this.props;
const { id } = params;
fetch(`/api/entries/${id}`, {
method: 'GET'
})
.then(response => response.json())
.then(
data => {
this.setState({
item: data
});
},
error => {
this.setState({
error
});
});
}
handleChangeEntry(e) {
this.setState({ entry: e.target.value });
}
handleChangeDescription(e) {
this.setState({ description: e.target.value });
}
handleSubmit(e) {
e.preventDefault();
const { entry, description } = this.state;
const { match: { params } } = this.props;
const { id } = params;
fetch(`/api/entries/${id}`, {
method: 'PUT',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(entry, description)
})
.then(response => {
if (response.ok) {
window.location.assign("/");
} else {
throw new Error('No response.');
}
},
error => {
this.setState({
error
});
});
}
render() {
const { item } = this.state;
const itemEditForm = item.map(i => {
return <div key={i.id}>
<form onSubmit={this.handleSubmit}>
<div className="form-group">
<label htmlFor="entry">Entry</label>
<input
id="entry"
name="entry"
type="text"
className="form-control"
required
value={i.entry}
onChange={this.handleChangeEntry} />
</div>
<div className="form-group">
<label htmlFor="description">Description</label>
<textarea
id="description"
name="description"
type="text"
className="form-control"
required
rows="5"
value={i.description}
onChange={this.handleChangeDescription} />
</div>
<button type="submit" className="btn btn-secondary btn-sm mb-sm-2">Submit</button>
</form>
</div>
});
return (
<div>
{itemEditForm}
</div>
);
}
}
export default EditEntry;
I can't edit the data contained in:
<input id="entry" (...) />
<textarea id="description" (...) />
There is data, there is a cursor, but these fields are disabled for editing.
I fetch an array with one object from the database (componentDidMount()). I know there is another way to access the data contained in an object. But that way in this project doesn't work. Although in my another project it works. Strange.
You are setting the "entry" and "description" properties in the onChange handler methods. but using the i.entry and i.description in the value property of the input. Please try changing it and maybe if you have multiple items in the item array, you can try something like below to handle state.
Component:
<input
id="name"
name="name"
type="text"
className="form-control"
required
value={i.name}
onChange={(e) => this.handleChangeName(e, i.id)}
/>
JS:
handleChangeName(e, id) {
console.log(e.target.value);
const newState = {
item: this.state.item.map((x) =>
x.id != id ? x : { id: id, name: e.target.value }
)
};
this.setState(newState);
}
Also, please find a working example based on your code on the CodeSandbox Link
Thanks.
I have a problem with my form submit. I am getting :ERR_EMPTY_RESPONSE after submit.
I want to send a form with photo. All looks good from postman. My POST is working, but when i want to use my form I am having an issue
This is my front end part
import React, { Component } from 'react';
import axios from 'axios';
import Button from '../../common/Buttons/Button';
import { API_URL } from '../../../config';
import { isAuthUser } from '../../../utils/utils';
class ProjectCreate extends Component {
state = {
formData: {
creator: '',
title: '',
description: '',
shortDescription: '',
photo: '',
tags: '',
projectType: '',
git: '',
demo: '',
},
displayLinks: false,
loading: false,
};
createProject = async (formData) => {
this.setState({ loading: true });
const { token } = isAuthUser();
const config = {
headers: {
Accept: 'application/json',
// 'Content-Type': 'application/json',
Authorization: `${token}`,
},
};
try {
console.log('axios data', formData);
await axios
.post(
`${API_URL}/projects/create/${this.props.match.params.userId}`,
formData,
config
)
.then((res) => res.data);
this.setState({ loading: false });
} catch (err) {}
};
onChange = (e) => {
// setting formData in the state properly
const { formData } = this.state;
let newFormData = { ...formData };
newFormData[e.target.name] = e.target.value;
this.setState({
formData: newFormData,
});
};
onSubmit = (e) => {
const { formData } = this.state;
e.preventDefault();
this.createProject(formData);
};
toggleLinks = () => {
const { displayLinks } = this.state;
if (!displayLinks) {
this.setState({ displayLinks: true });
} else {
this.setState({ displayLinks: false });
}
};
render() {
const {
displayLinks,
formData: {
title,
description,
shortDescription,
photo,
tags,
projectType,
git,
demo,
},
} = this.state;
return (
<section className=''>
<h1 className=''>Create Project</h1>
<p className=''>
<i className='fas fa-user'></i> Add project information
</p>
<small>* = required field</small>
<form
encType='multipart/form-data'
className='form'
onSubmit={(e) => this.onSubmit(e)}>
<div className=''>
<select
name='projectType'
value={projectType}
onChange={this.onChange}>
<option value='0'>* Select Project Type Status</option>
<option value='Front-end'>Front-end</option>
<option value='Back-end'>Back-end</option>
<option value='MERN'>MERN</option>
<option value='Vanila JS'>Vanila JS</option>
<option value='html'>HTML/CSS</option>
</select>
<small className='form-text'>Select a project type.</small>
</div>
<div className='form-group'>
<input
type='text'
placeholder='Title'
name='title'
value={title}
onChange={this.onChange}
/>
<small className='form-text'>Add project title.</small>
</div>
<div className='form-group'>
<input
type='text'
placeholder='Description'
name='description'
value={description}
onChange={this.onChange}
/>
<small className='form-text'>Add project description</small>
</div>
<div className='form-group'>
<input
type='text'
placeholder='Short description'
name='shortDescription'
value={shortDescription}
onChange={this.onChange}
/>
<small className='form-text'>Add project short description</small>
</div>
<div className='form-group'>
<input
type='text'
placeholder='* Tags'
name='tags'
value={tags}
onChange={this.onChange}
/>
<small className='form-text'>
Please use comma separated values (eg. HTML,CSS,JavaScript,PHP)
</small>
</div>
<div className='form-group'>
<input
type='file'
accept='.jpg, .png, .jpeg'
placeholder='Photo'
name='photo'
value={photo}
onChange={this.onChange}
/>
<small className='form-text'>Add project preview.</small>
</div>
<div className='my-2'>
<button onClick={this.toggleLinks} type='button' className=''>
Add Project Links
</button>
<span>Optional</span>
{displayLinks && (
<div>
<div className=''>
<i className=''></i>
<input
type='text'
placeholder='Git URL'
name='git'
value={git}
onChange={this.onChange}
/>
</div>
<div className=''>
<i className=''></i>
<input
type='text'
placeholder='Demo URL'
name='demo'
value={demo}
onChange={this.onChange}
/>
</div>
</div>
)}
</div>
<input type='submit' className='btn btn-primary my-1' />
<Button className='btn btn-light my-1' to='/projects'>
Go Back
</Button>
</form>
</section>
);
}
}
export default ProjectCreate;
My state is change when I type in form and my console.log is returning formData
This is my POST
/* create projects */
exports.create = (req, res) => {
let form = new formidable.IncomingForm();
form.keepExtensions = true;
form.parse(req, (err, fields, files) => {
if (err) {
return res
.status(400)
.json({ errors: [{ msg: 'Image could not be uploaded' }] });
}
const { git, demo } = fields;
fields.creator = req.user._id;
fields.links = {};
if (git) fields.links.git = git;
if (demo) fields.links.demo = demo;
let project = new Project(fields);
//1kb = 1000
//1mb = 1000000kb
//name 'photo' mus match client side. use photo
if (files.photo) {
if (files.photo.size > 1000000) {
return res.status(400).json({
errors: [{ msg: 'Image could not be uploaded. File to big.' }],
});
}
//this relates to data in schema product
project.photo.data = fs.readFileSync(files.photo.path);
project.photo.contentType = files.photo.type;
}
project.save();
console.log('project backend', project);
return res.json(project);
});
};
I am using formidable for photo upload. not sure why this stopped working
I'm not familiar with Formidable, but this may help with troubleshooting the issue.
Since it is working successfully in PostMan, have you tried setting other responses based on their response code ex. res.status(200).json({success: true}) in order to troubleshoot the back end?
I have done this with Express projects in the past and it makes it a lot easier for me to find exactly where the problem is. When I find where I start to see the error, I always work backwards from there until I find the issue.
Proper way to set response status and JSON content in a REST API made with nodejs and express
I am trying to structure my API call to the openweatherapi properly, just trying to create a simple weather app, where upon the user entering a city the forecast is rendered to the page. This is what I have so far, also trying to prevent the default action where the page refreshes when the button is pressed. I am using react.
class App extends Component {
getWeatherData = (userInput, event) => {
event.preventDefault();
axios({
url: "http://openweathermap.org/data/2.5/weather/",
method: "GET",
dataType: "json",
data: {
q: userInput,
API_KEY: "d108038ec889cfe762230283abaa7c7b"
}
}).then(res => {
console.log(res);
this.setState({});
});
};
./Form. js is as follows
class Form extends Component {
render() {
return (
<div>
<form onSubmit={(this.props.getWeather, e)}>
<input type="text" name="city" placeholder="City..." />
<input type="text" name="country" placeholder="Country" />
<button>Get Weather</button>
</form>
</div>
);
}
}
Error:
./src/Form.js
Line 7: 'e' is not defined no-undef
Using class components, I would do something like this :
(each class/function should be split in a different file)
/**
* This is just a helper to encapsulate the weather fetching logic
*/
function getWeatherFromInput({ city, country }) {
const query = `${city},${country}`;
return axios({
method: 'GET',
url: `http://openweathermap.org/data/2.5/weather?${query}`,
responseType: 'json'
});
}
/**
* Here is the specific form
*/
export class WeatherForm extends React.Component {
constructor(props) {
super(props);
this.state = {
city: '',
country: ''
};
}
handleSubmit = (event) => {
event.preventDefault();
this.props.onSubmit(this.state);
};
handleInputChange = (event) => {
const { name, value } = event.target;
this.setState({ [name]: value });
};
render() {
const { city, country } = this.state;
return (
<form onSubmit={this.handleSubmit}>
<input
type='text'
name='city'
value={city}
onChange={this.handleInputChange}
placeholder='City...'
/>
<input
type='text'
name='country'
value={country}
onChange={this.handleInputChange}
placeholder='Country'
/>
<button type='submit'>Get weather</button>
</form>
);
}
}
/**
* And how you use it in your App
*/
export class App extends React.Component {
constructor() {
this.state = {
weather: {}
};
}
/**
* The userInput is provided by the WeatherForm
*/
handleSubmit = (userInput) => {
getWeatherFromInput(userInput).then((response) => {
this.setState({ weather: response.data });
});
};
render() {
return <WeatherForm onSubmit={handleSubmit} />;
}
}
You can just move your form to your app class, passing up form data between components doenst work perfectly in react.
class App extends Component {
getWeatherData = (event) => {
const userInput = {
event.target.city.value,
event.target.country.value
}
event.preventDefault();
axios({
url: "http://openweathermap.org/data/2.5/weather/",
method: "GET",
dataType: "json",
data: {
q: userInput,
API_KEY: "d108038ec889cfe762230283abaa7c7b"
}
}).then(res => {
console.log(res);
this.setState({});
});
render() {
return (
<div>
<form onSubmit={this.getWeatherData}>
<input type="text" name="city" placeholder="City..." />
<input type="text" name="country" placeholder="Country" />
<button>Get Weather</button>
</form>
</div>
);
}
}
You also dont need to specify the userInput as a parameter you can set inside your function by accessing the values with the event keyword.