I am trying to send the form data of react component to the server through using axios or fetch.
All of the code I wrote failed (in onSubmit).
My server's port is 5000.
I have already set bodyParser in server.js as well.
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
// React Component
const Voting = ({ history }) => {
const [hasQuery, setQuery] = useState('');
const [formData, setFormData] = useState({
cat: false,
dog: false,
});
const { cat, dog } = formData;
const onChange = e => {
let obj = {};
obj[e.target.name] = e.target.checked;
setFormData(obj);
};
const onSubmit = async e => {
e.preventDefault();
1.
// axios.post('http://localhost:5000/main', { formData }).then(result => {
// console.log(result, 'result');
// });
2.
fetch('http://localhost:5000/main', {
method:'post',
body: formData
})
.then(res => res.json())
.then(data => alert(data.msg));
3.
// fetch('http://localhost:5000/main', {
// method: 'post',
// headers: {
// 'Content-Type': 'application/json; charset=utf-8'
// },
// body: JSON.stringify(formData),
// })
// .then(res => res.json())
// .then(obj => {
// if (obj.result === 'succ') {
// alert('Move on to the next.');
// }
// });
history.push(`/success`);
};
return (
<div>
<p>{hasQuery}</p>
<form
className='mode-container'
onSubmit={onSubmit}
mathod='POST'
action='http://localhost:5000/main'
>
<h3>Choose what you like more</h3>
<div>
<label>
cat
<input
type='radio'
name='cat'
value={cat}
onChange={onChange}
/>
</label>
<label>
dog
<input
type='radio'
name='dog'
value={dog}
onChange={onChange}
/>
</label>
</div>
<button type='submit'></button>
</form>
</div>
);
};
const mapStateToProps = state => ({
isAuthenticated: state.auth.isAuthenticated,
});
export default connect(mapStateToProps)(Voting);
And below is the code I wrote in node.js. req.body is an empty object.
// Node.js
mainRouter.post(
'/',
(req, _res, _next) => console.log(req, 'req.body'),
);
You are targeting /main in all of your client calls, but on server you only have / route.
Try the following:
axios.post('http://localhost:5000/', { formData }).then(result => {
console.log(result, 'result');
});
Or - change the server route:
mainRouter.post(
'/main',
(req, _res, _next) => console.log(req, 'req.body'),
);
Related
All the answers related this error is directing towards checking the name upload.single("image") and the name attribute of the file input in client side, which is in my case same as "image" as multer. But still it is giving the error.
Following is the node js code:
const Imagestorage = multer.memoryStorage()
const upload = multer({ storage: Imagestorage })
app.post("/newpost", upload.single("image"), async(req, res) => {
console.log(req.body);
console.log(req.file);
let data={}
// convert base64 image data to string using datauri/parser, upload to cloudinary and send response
const extName = path.extname(req.file.originalname).toString();
const file64 = parser.format(extName, req.file.buffer);
const filename=file64.content
cloudinary.uploader.upload(filename, async(error, result) => {
if (error) {
res.status(500).send("error in uploading file to cloudinary"+error);
} else {
// result.secure_url is the URL of the uploaded file on Cloudinary
console.log(result.secure_url);
let Imageurl=await result.secure_url
data={
name: req.body.name,
location:req.body.location,
likes:req.body.likes,
description:req.body.description,
image:Imageurl
}
console.log(data)
let postedData=await postsModel.create(data)
res.json({
status:"ok",
postedData
})
}
});
});
//error field in case something happens with multer
// app.use((error, req, res, next) => {
// console.log('This is the rejected field ->', error.field);
// });
app.get("*", (req, res) => {
res.status(404).send("PAGE IS NOT FOUND");
})
Frontend code-
import axios from "axios";
import { useNavigate } from "react-router-dom";
const Form = () => {
const navigate = useNavigate();
function handleSubmit(event) {
event.preventDefault();
const formData = new FormData(event.target);
// Append the file input to the form data
const imageFile = formData.get("image");
formData.append("image", imageFile);
// Use Axios to send a POST request to your server with the form data
axios
.post("https://instabackend-gcwk.onrender.com/newpost", formData, {
//.post("http://127.0.0.1:5000/newpost", formData, {
headers: {
"Content-Type": "multipart/form-data"
}
})
.then((response) => {
console.log(response);
})
.catch((error) => {
console.error(error);
})
.finally(navigate("/insta"));
}
return (
<div>
<form onSubmit={handleSubmit}>
<label htmlFor="image">Image:</label>
<input type="file" id="image" name="image" accept="image/*" />
<button type="submit">Submit</button>
</form>
<button onClick={() => navigate(-1)}>Go Back Home</button>
</div>
);
};
export default Form;
When i tried -
app.use((error, req, res, next) => {
console.log('This is the rejected field ->', error.field);
});
it's giving error field as "This is the rejected field -> image "
Note: There is no issue in fetching the data
Replacing append with set of FormData() is making the code work. Javascript.info explains the working of formData() here
import axios from "axios";
const App = () => {
function handleSubmit(event) {
event.preventDefault();
const formData = new FormData(event.target);
//get image
const imageFile = formData.get("image");
//set image
formData.set("image", imageFile);
axios
.post("https://instabackend-gcwk.onrender.com/newpost", formData, {
headers: {
"Content-Type": "multipart/form-data"
}
})
.then((response) => {
console.log(response);
})
.catch((error) => {
console.error(error);
});
}
return (
<div>
<form onSubmit={handleSubmit}>
<label htmlFor="image">Image:</label>
<input type="file" id="image" name="image" accept="image/*" />
<button type="submit">Submit</button>
</form>
</div>
);
};
export default App;
I am very new to backend so I am trying to implement a simple Notion form on a Typescript website. I was following this tutorial: https://commotion.page/blog/how-to-create-a-form-app-with-the-notion-api to learn how to post from localhost:3000 to the Notion backend database which looks exactly like the one in the tutorial. However, every time I reload the page I get this error:
Here is the code for my express server, app.js (exactly the same as the one in the tutorial):
const express = require('express')
const axios = require('axios')
const cors = require('cors')
const app = express()
const port = 3002
const secretKey = 'secret_[KEY REPLACED]'
const headers = {
'Content-Type': 'application/json',
Authorization: `Bearer ${secretKey}`,
'Notion-Version': '2022-02-22',
}
app.post('/704f58825cf841759f76733c5794e8aa', async (req, res) => {
const { name, email } = req.body
await axios({
method: 'POST',
url: 'https://api.notion.com/v1/pages',
headers,
data: {
parent: { dat704f58825cf841759f76733c5794e8aaabase_id },
properties: {
"Name": { "title": [{ text: { content: name } }] },
"Email": { "email": email }
}
}
})
})
app.get('/:database_id', async (req, res) => {
const { database_id } = req.params;
const resp = await axios({
method: 'GET',
url: 'https://api.notion.com/v1/databases/' + database_id,
headers
});
return res.json(resp.data)
})
app.use(cors())
app.use(express.json())
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
I am using ChakraUI for my front-end as well. This is the code for my main app, which is located outside of the server folder in the main app folder:
const database_id = '[KEY REPLACED]';
export default function ContactFormWithSocialButtons() {
const { hasCopied, onCopy } = useClipboard('intellimindsBR#gmail.com');
const [db, setDB] = useState({});
const [email, setEmail] = useState('');
const [name, setName] = useState('');
const onSubmit = (e) => {
e.preventDefault();
console.log(name);
console.log(email);
fetch('http://localhost:3002/' + database_id, {
method: 'POST',
body: JSON.stringify({ email: email, name: name }),
headers: { "Content-Type": 'application/json' }
});
}
useEffect(() => {
fetch('http://localhost:3002/' + database_id).then(async (resp) => {
setDB(await resp.json());
});
}, []);
return (
<Box
bg={useColorModeValue('white', 'gray.700')}
borderRadius="lg"
p={8}
color={useColorModeValue('gray.700', 'whiteAlpha.900')}
shadow="base">
<VStack spacing={5}>
<form onSubmit={onSubmit}>
<FormControl isRequired>
<FormLabel>Name</FormLabel>
<InputGroup>
<InputLeftElement children={<BsPerson />} />
<Input type="text" name="name" placeholder="Your Name"
onChange={event => setName(event.currentTarget.value)} />
</InputGroup>
</FormControl>
<FormControl isRequired>
<FormLabel>Email</FormLabel>
<InputGroup>
<InputLeftElement children={<MdOutlineEmail />} />
<Input
type="email"
name="email"
placeholder="Your Email"
onChange={event => setEmail(event.currentTarget.value)}
/>
</InputGroup>
</FormControl>
<Button
type="submit"
colorScheme="blue"
bg="blue.400"
color="white"
_hover={{
bg: 'blue.500',
}}>
Send Message
</Button>
</form>
</VStack>
</Box>
);
}
When I load the server with node app.js, everything works fine and the title of the database successfully loads onto the production page but as soon as I enter data to submit in the form I get this response:
I also get this error in console for my app.js page when I submit the form:
const { name, email } = req.body
^
TypeError: Cannot destructure property 'name' of 'req.body' as it is undefined.
I will also mention that when I load the server with node app.js, the error Cannot GET / but all the data loads fine when I go to the API URL with the database ID in the URL (http://localhost:3002/[database ID]).
I have properly configured the Notion API integration and I have tried enabling Access-Control-Allow-Origin for Chrome, but I'm still facing these errors.
Before you can access req.body, you must use a body-parsing middleware like express.json:
app.post('/704f58825cf841759f76733c5794e8aa',
express.json(),
async (req, res) => {
const { name, email } = req.body
...
})
I can successfully upload images to Cloudinary. But my question is how can I get the Cloudinary url of the successfully uploaded image sent back to me immediately upon upload?
I know it's sent back as part of const uploadedResponse = await cloudinary.uploader.upload(fileStr, {upload_preset: 'dev_setups'}), but this is on the backend (see code #2 below), I would like to receive the URL on the frontend (see code #1 below) so I can set it to React state. What is the best approach to accomplishing this?
Please let me know if you need more details.
Code #1: Below is my code to upload a picture to Cloudinary (Cloudinary specific code is commented below for reference as /* Cloudinary upload */)
import React, { useState } from 'react'
import { Card, Button, CardContent } from '#material-ui/core';
import { post, makePostAction } from '../actions';
import { useSelector, useDispatch } from 'react-redux';
export default function MakePost() {
const [title, setTitle] = useState("")
const dispatch = useDispatch();
const usernameHandle = useSelector(state => state.username)
const [fileInputState, setFileInputState] = useState('') /* new */
const [previewSource, setPreviewSource] = useState('') /* new */
const [selectedFile, setSelectedFile] = useState('') /* new */
const onInputChange = (event) => {
setTitle(event.target.value);
}
const handleSubmit = (evt) => {
evt.preventDefault();
if (!title) return
dispatch(makePostAction({
title,
comment: false,
comments_text: "",
handle: usernameHandle,
post_date: new Date().getTime()
}))
setTitle("")
}
/* Cloudinary upload */
const handleFileInputChange = (e) => {
const file = e.target.files[0]
previewFile(file)
}
const previewFile = (file) => {
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onloadend = () => {
setPreviewSource(reader.result)
}
}
const handleSubmitFile = (e) => {
e.preventDefault();
if(!previewSource) return;
uploadImage(previewSource)
}
const uploadImage = async (base64EncodedImage) => {
console.log(base64EncodedImage)
try {
await fetch('/api/upload', {
method: 'POST',
body: JSON.stringify({data: base64EncodedImage}),
headers: {'Content-type': 'application/json'}
})
} catch (error) {
console.error(error)
}
}
/* Cloudinary upload */
return (
<div>
<Card>
<CardContent>
<form onSubmit={handleSubmit}>
<input type="text" value={title} onChange={onInputChange} />
</form>
{/* new */}
<form onSubmit={handleSubmitFile} className="form">
<input type="file" name="image" onChange={handleFileInputChange} value={fileInputState} className="form-input" />
<button className="btn" type="submit">Submit</button>
</form>
{/* new */}
{previewSource && (
<img
src={previewSource}
alt="chosen"
style={{height: '300px'}}
/>
)}
</CardContent>
</Card>
</div>
)
}
Code #2: Here is my server.js
const express = require('express');
const app = express();
const {cloudinary} = require('./utils/cloudinary');
app.use(express.json({limit: '50mb'}));
app.use(express.urlencoded({limit: '50mb', extended: true}))
app.get('/api/images', async (req, res) => {
const {resources} = await cloudinary.search.expression('folder:dev_setups')
.sort_by('public_id', 'desc')
.max_results(1)
.execute()
const publicIds = resources.map(file => file.secure_url)
res.send(publicIds)
})
app.post('/api/upload', async (req, res) => {
try {
const fileStr = req.body.data;
const uploadedResponse = await cloudinary.uploader.upload(fileStr, {upload_preset: 'dev_setups'})
res.json({msg: "Success"})
} catch (error){
console.error(error)
res.status(500).json({err: 'Something went wrong'})
}
})
const port = process.env.PORT || 3001
app.listen(port, () => {
console.log(`listening on port ${port}`)
});
The Cloudinary upload response object includes a secure_url attribute which you can send back to the front end. Looking at code #2, it seems that you're currently sending a "Success" msg (res.json({msg: "Success"})). Sounds like you want to change that line to -
res.json({url: uploadedResponse.secure_url})
In your front end (code #1), I'd consider switching from async/await to .then mechanism, as you don't want to the entire app to wait for the response -
const uploadImage = (base64EncodedImage) => {
console.log(base64EncodedImage);
fetch('/api/upload', {
method: 'POST',
body: JSON.stringify({data: base64EncodedImage}),
headers: {'Content-type': 'application/json'}
})
.then(doWhateverYouWant)
.catch((error) => console.error(error))
}
const doWhateverYouWant = async (res) => {
// you can use res.url
}
I am trying to send formdata from react to express server. When sending json payload, i get what is expected. However, when sending data using formdata.append, i get empty req body.
I tried various solutions posted here for similar problem but nothing seemed to work for me.
Hope someone can help
app.js
require('./database/db')
const express = require('express')
const cors = require('cors')
const userRouter = require('./routes/user')
const menuRouter = require('./routes/menu')
const app = express()
app.use(express.json())
app.use(express.urlencoded({ extended: true }))
app.use(cors())
app.use(express.static('public'))
app.use(userRouter)
app.use(menuRouter)
app.listen(9000, () => console.log('Server started at port: 9000'))
route i want to call
router.post(
'/addMenu',
[
check('name', 'Menu name is required!').not().isEmpty(),
check('price', 'Price is required!').not().isEmpty(),
check('category', 'Category is required!').not().isEmpty(),
],
verifyAuth,
(req, res) => {
console.log(req.body)
// body is empty here
})
react bootstrap form
import { Component } from 'react'
import axios from '../axios'
import { Link } from 'react-router-dom'
import { Button, Form, Card } from 'react-bootstrap'
export default class AddMenu extends Component {
constructor(props) {
super(props)
this.state = {
name: '',
price: '',
category: '',
image: '',
}
this.inputHandler = this.inputHandler.bind(this)
this.inputHandler = this.inputHandler.bind(this)
this.addMenu = this.addMenu.bind(this)
}
inputHandler = (e) => {
this.setState({
[e.target.name]: e.target.value,
})
}
fileHandler = (e) => {
this.setState({
image: e.currentTarget.files[0],
})
}
addMenu = (e) => {
e.preventDefault()
const { name, price, category, image } = this.state
const data = new FormData()
data.append('name', name)
data.append('price', price)
data.append('category', category)
data.append('file', image)
axios
.post('/addMenu', data)
.then((response) => {
if (response.data.success) {
alert(response.data.menu)
} else {
alert('something went wrong')
}
})
.catch()
}
render() {
return (
<div className='col-lg-12 col-centered' style={{ height: '44rem' }}>
<Card
style={{
width: '20rem',
marginLeft: '420px',
marginTop: '80px',
float: 'left',
height: '34rem',
}}
>
<Card.Img
variant='top'
src='https://image.freepik.com/free-vector/food-delivery-service-fast-food-delivery-scooter-delivery-service-illustration_67394-869.jpg'
/>
<Card.Body>
<Card.Title>Add Menu</Card.Title>
<Card.Text>
Although a great restaurant experience must include great food, a bad restaurant experience can be achieved through bad service alone.
Ideally, service is invisible.
</Card.Text>
<Button as={Link} to='/' variant='info'>
Go to Home
</Button>
</Card.Body>
</Card>
<Card
style={{
width: '22rem',
marginTop: '78px',
float: 'left',
height: '34rem',
}}
>
<Form className='add-menu' onSubmit={this.addMenu}>
<h2>Add Menu</h2>
<Form.Group controlId='formBasicName'>
<Form.Label>Restaurant Name</Form.Label>
<Form.Control
type='text'
name='name'
placeholder='Enter Restaurant Name'
value={this.state.name}
onChange={(event) => this.inputHandler(event)}
/>
</Form.Group>
<Form.Group controlId='formBasicPrice'>
<Form.Label>Enter Price</Form.Label>
<Form.Control type='text' name='price' placeholder='Price' value={this.state.price} onChange={(event) => this.inputHandler(event)} />
</Form.Group>
<Form.Group controlId='formBasicCategory'>
<Form.Label>Enter Category</Form.Label>
<Form.Control
name='category'
type='text'
placeholder='Enter Menu Category'
value={this.state.category}
onChange={(event) => this.inputHandler(event)}
/>
</Form.Group>
<Form.Group controlId='formBasicImage'>
<Form.Label>Enter Category</Form.Label>
<Form.Control name='image' type='file' onChange={this.fileHandler} />
</Form.Group>
<Button className='btn-lg btn-block' variant='info' type='submit'>
Add Menu
</Button>
</Form>
</Card>
<br />
<br />
<br />
</div>
)
}
}
routes/menu implementation
const router = require('express').Router()
const { verifyAuth } = require('../middleware/auth')
const upload = require('../middleware/fileUpload')
const Menu = require('../models/Menu')
const { check, validationResult } = require('express-validator')
// add a menu item
router.post(
'/addMenu',
[
check('name', 'Menu name is required!').not().isEmpty(),
check('price', 'Price is required!').not().isEmpty(),
check('category', 'Category is required!').not().isEmpty(),
],
verifyAuth,
(req, res) => {
console.log(req.body)
if (req.authUser.userType === 'Restaurant') {
const validationErr = validationResult(req)
if (validationErr.isEmpty()) {
let image = null
const { name, price, category } = req.body
if (req.file) {
upload(req, res, (err) => {
if (err) {
response.status(500).json({ success: false, message: err })
} else {
image = req.file.filename
}
})
}
const newMenu = new Menu({ name, price, category, addedBy: req.authUser._id, image })
newMenu
.save()
.then((menu) => res.status(201).json({ success: true, message: 'Menu added', menu }))
.catch((error) => res.status(500).json({ success: false, message: error.message }))
} else {
res.status(400).json({ success: false, errors: validationErr.array() })
}
} else {
res.status(403).json({ success: true, message: 'Insufficient privileges' })
}
}
)
// get all menu items
router.get('/menus', (req, res) => {
Menu.find()
.populate('addedBy', '-_id name')
.then((menus) => res.status(200).json({ success: true, menus }))
.catch((error) => res.status(500).json({ success: false, message: error.message }))
})
module.exports = router
Even in Postman x-www-form-urlencoded sends the data but form-data does not
Form data will get empty object if there is no file given to it via routes like this.
import multer from 'multer';
router.post(
'/addMenu',
multer().single("keyNameForFile"),
[
check('name', 'Menu name is required!').not().isEmpty(),
check('price', 'Price is required!').not().isEmpty(),
check('category', 'Category is required!').not().isEmpty(),
],
verifyAuth,
(req, res) => {
console.log(req.body)
// body is empty here
})
Don't know what cause this behaviour but use form-data when you are sending some file like image doc etc.
You should set the Content-Type of your request header as Content-Type: application/x-www-form-urlencoded this will allow express to access you form data in the body
To set the header in axios you can perform it like this
const config = {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
};
and you perform a request to you backend with the header set like this
axios.post('/addMenu', data, config)
.then({ /*...*/});
in your axios request you will need to specify the content type in the headers
of the request. What I usually do also, is specify my agrs as an object for just
for annotation purposes
like this:
axios({
method: 'post',
url: '/addMenu',
data: data,
headers: { 'Content-Type': 'application/json' },
})
.then((response) => {
if (response.data.success) {
alert(response.data.menu)
} else {
alert('something went wrong')
}
})
.catch((error) => {
//handle error
console.log(error);
});
EDIT:
I just noticed that you are trying to send a file as well...haha
to send a file through to express, you will need to get the package called multer to handle file uploads for you
npm i --save multer
then add it when configuring your server
const multer = require('multer');
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
app.use(cors());
app.use(multer().any());
once you have that done, in your request on the axios side, do it like this:
axios({
method: 'post',
url: '/addMenu',
data: data,
headers: { 'Content-Type': 'multipart/form-data' },
})
.then((response) => {
if (response.data.success) {
alert(response.data.menu)
} else {
alert('something went wrong')
}
})
.catch((error) => {
//handle error
console.log(error);
});
and finally, to handle your files on your server they will show in the request
object like this:
request.files // which will be an array of file objects
please try this...i know its long but i had this issue once and used this solution
As per #ash.io answer BIG NOTICE for MERN stackers! : my case was as it used to return empty object , but when I added (mounted) app.use(express.json()) middleware all sorted out ! Currently MongoDB shows results just fine ! For anyone who interested into quick useForm snippet , here it goes React-useForm boilerplate
I made a Spotify web app and launched it with Netlify. When I run its server file, it works well on my computer but not on my friend's. I thought it was because of the Spotify API at first but another web app I made, which doesn't use any API, only works on my computer as well. I think it's because of the server port or something but I'm not sure how to fix it.
Here's the website url and the server side code.
https://xenodochial-kepler-118793.netlify.app
server.js
const express = require("express");
const SpotifyWebApi = require("spotify-web-api-node");
const bodyParser = require("body-parser");
const cors = require("cors");
const app = express();
const port = 4000 || process.env.PORT;
require("dotenv").config();
app.use(express.json());
app.use(cors());
app.use(bodyParser.urlencoded({ extended: true }));
// Create the api object with the credentials
var spotifyApi = new SpotifyWebApi({
clientId: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
});
// Retrieve an access token.
function newToken() {
spotifyApi.clientCredentialsGrant().then(
function (data) {
console.log("The access token expires in " + data.body["expires_in"]);
// Save the access token so that it's used in future calls
spotifyApi.setAccessToken(data.body["access_token"]);
},
function (err) {
console.log("Something went wrong when retrieving an access token", err);
}
);
}
newToken();
tokenRefreshInterval = setInterval(newToken, 1000 * 60 * 60);
app.post("/search_result", (req, res) => {
spotifyApi
.searchArtists(req.body.keyword)
.then(function (data) {
let search_res = data.body.artists.items;
res.json(search_res);
res.end();
})
.catch((err) => {
console.log(err);
res.status(500).send(err);
});
});
app.get("/albums/:id", (req, res) => {
console.log(req.params.id);
spotifyApi
.getArtistAlbums(req.params.id, { limit: 40 })
.then(function (data) {
res.json(data.body.items);
res.end();
});
});
app.get("/albums/tracks/:albumID", (req, res) => {
console.log(req.params.albumID);
spotifyApi
.getAlbumTracks(req.params.albumID, { limit: 20 })
.then(function (data) {
console.log(data.body);
res.json(data.body.items);
res.end();
});
});
app.listen(port, () => console.log(`It's running on port ${port}`));
Main.js
import React, { Component } from "react";
import SingerBox from "./SingerBox";
import axios from "axios";
import "../../App.css";
export class Main extends Component {
constructor(props) {
super(props);
this.state = {
keyword: "",
artists: [],
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(e) {
this.setState({ keyword: e.target.value });
}
handleSubmit(e) {
e.preventDefault();
if (this.state.keyword === "") {
alert("Enter Search Keyword");
}
axios
.post(
"/search_result",
{
keyword: this.state.keyword,
},
{
headers: {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
},
}
)
.then((res) => {
this.setState({ artists: res.data });
})
.catch((err) => {
console.log(err);
});
}
render() {
return (
<div className="container">
<div className="main">
<form onSubmit={this.handleSubmit}>
<label className="header" htmlFor="search">
Explore New Artists
</label>
<span>
<input
className="search-box"
type="search"
value={this.state.keyword}
onChange={this.handleChange}
name="keyword"
placeholder="Search artists..."
/>
<button className="submit-btn" type="submit" value="Submit">
Search
</button>
</span>
</form>
<br />
{this.state.artists.map((elem) => (
<SingerBox images={elem.images} name={elem.name} id={elem.id} />
))}
<br />
</div>
</div>
);
}
}
export default Main;
You have hardcoded localhost in your code somewhere. The apis are hitting your local server when someone is searching for the artist.
Remove localhost from code and every thing should work fine.