React Axios Post Always return Cannot post - reactjs

Well my problem its that always that i send the login info to the backend, react return me Cannot Post /login. The problem its that i have a res.redirect to the main page but it dosent work and i dont know if its an error of Axios or the controller, because the information arrives correctly. What do you think? What issue im having?
React Login
import React, {Component} from "react";
import "./user.css"
import Api from "../Instrumentos/apiInstrumentos"
import { withRouter } from "react-router";
class User extends Component {
constructor(props){
super(props);
this.state = {
user: []
}
};
async componentDidMount(){
try{
console.log()
const id = this.props.match.params.id;
let user = await fetch(`http://localhost:5000/user/${id}`).then(response =>
response.json())
this.setState({
user: user
});
console.log(this.state.user)
}
catch(error){
console.log(error);
}
}
render(){
let user = this.state.user
return (
<section id="user-detail">
<section id="user_saved">
<article>
<figure id="user_figure">
<img src={`http://localhost:5000${user.photo}`} />
</figure>
<h3 id="bienvenido_user">Bienvenido {user.nombre}</h3>
<form className="margin-sections">
<fieldset>
<input type="text" name="" placeholder={user.nombre}
className="input-profile"></input>
</fieldset>
<fieldset>
<input type="text" name="apellido" placeholder={user.apellido}
className="input-profile"></input>
</fieldset>
<fieldset>
<input type="password" name="password" placeholder={user.password}
className="input-profile"></input>
</fieldset>
<fieldset>
<button className="button-login button-detail"
type="submit">Enviar</button>
</fieldset>
</form>
</article>
<article>
<h3 id="Instrumentos_guardados">Instrumentos Guardados</h3>
<Api />
</article>
</section>
</section>
);
}
}
useForm Hook
import {useState} from 'react';
import Axios from 'axios';
export const useForm = (initialForm, validateForm) => {
const [form, setForm] = useState(initialForm);
const [errors, setErrors] = useState({});
const [loading,] = useState(false);
const [response,] = useState(null);
const handleChange = (e) => {
const { name,value } = e.target;
setForm({
...form,
[name]: value
});
};
const handleBlur = (e) => {
handleChange(e);
setErrors(validateForm(form));
};
const handleSubmit = (e) => {
setErrors(validateForm(form));
Axios
.post('http://localhost:5000/usuarios/login', form)
.then(response => {
console.log(response)
})
.then(data => console.log(data))
.catch(error => {
console.log(error)
})
};
return {
form,
errors,
loading,
response,
handleChange,
handleBlur,
handleSubmit
};
}
Backend Controller
const main = {
acceso: async (req, res) => {
console.log(req.body)
return res.redirect("http://localhost:3000")
}
}
Backend Routes
const express = require('express');
const router = express.Router();
const path = require("path");
const fs = require("fs");
const user = require("../controllers/user");
const multer = require("multer");
// ************ Multer ************
const dest = multer.diskStorage({
destination: function (req, file, cb) {
let dir = path.resolve(__dirname,"../../public/uploads","users",
String(req.body.nombre).trim().replace(/\s+/g, ''))
if (!fs.existsSync(dir)){
fs.mkdirSync(dir);
}
cb(null, dir)
},
filename: function (req, file, cb) {
cb(null, file.fieldname + '-' + Date.now()+ path.extname(file.originalname))
}
})
const upload = multer({storage:dest});
// ************ Routes ************
router.post("/login", user.acceso)
router.post('/guardar', upload.single("file") , user.post)
module.exports = router;
/*** Entry Point ***/
Entry point Route definition
const users = require("./routes/user");
app.use("/usuarios", users);
/*** Console.log ***/
Console.log Response { email: 'juansepincha#gmail.com', password: '12345' }
From now thanks for all and have a great weekend!

Related

Weird CORS issue with login in React?

I have a small issue here. Basically I am trying to work on a login/register system built in React.
This is how I handle the signup:
const submitHandler = async (data: object) => {
console.log(data);
await fetch("http://localhost:4000/signup", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
.then((res) => res.json())
.then((data) => {
if (data.status_code === "SUCCESS") {
router.push("/login");
}
})
.catch((err) => console.log(err));
};
That works perfectly fine and also saves the data in the database after signing up, but my login has some issues not handling the user (redirecting him)
const submitHandler = async (data: object) => {
await fetch("http://localhost:4000/login", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
.then((res) => res.json())
.then((data) => {
if (data.status_code === "SUCCESS") {
localStorage.setItem("userData", JSON.stringify(data.data));
router.push("/dashboard");
} else {
setError("Invalid Credentials!");
}
})
.catch((err) => console.log(err));
};
When I enter the correct data from the signup, nothing really happens (it should set the jwt token into the localstorage and then redirect me to the dashboard route), any ideas?
This is not redirecting you to login route because if you clearly look at bottom of your signup request handler where you are comparing data.status_code === " SUCCESS" that should be data.status_code === "SUCCESS".
"SUCCESS" & " SUCCESS" both are different.
For me it seems like that you have a typo when you check the data.status_code. You misspelled " SUCCESS" with "SUCCESS". If that was the case, then you can move on, but here is an alternate solution you could use. I also provided a back-end file (I used Node.js with Express).
import React, { useState } from 'react';
import PropTypes from 'prop-types';
async function submitHandler(credentials) {
return fetch('http://localhost:4000/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(credentials)
})
.then(data => data.json())
}
export default function Login({ setToken }) {
const [username, setUserName] = useState();
const [password, setPassword] = useState();
const handleSubmit = async e => {
e.preventDefault();
const token = await submitHandler({
username,
password
});
setToken(token);
}
return(
<div className="login-wrapper">
<h1>Please Log In</h1>
<form onSubmit={handleSubmit}>
<label>
<p>Username</p>
<input type="text" onChange={e => setUserName(e.target.value)} />
</label>
<label>
<p>Password</p>
<input type="password" onChange={e => setPassword(e.target.value)} />
</label>
<div>
<button type="submit">Submit</button>
</div>
</form>
</div>
)
}
Login.propTypes = {
setToken: PropTypes.func.isRequired
};
useToken.js - contains the logic for the custom hook
import { useState } from 'react';
export default function useToken() {
const getToken = () => {
const tokenString = localStorage.getItem('token');
const userToken = JSON.parse(tokenString);
return userToken?.token
};
const [token, setToken] = useState(getToken());
const saveToken = userToken => {
localStorage.setItem('token', JSON.stringify(userToken));
setToken(userToken.token);
};
return {
setToken: saveToken,
token
}
}
App.js
import React from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import './App.css';
import Dashboard from '../Dashboard/Dashboard';
import Login from '../Login/Login';
import Preferences from '../Preferences/Preferences';
import useToken from './useToken';
function App() {
const { token, setToken } = useToken();
if(!token) {
return <Login setToken={setToken} />
}
return (
<div className="wrapper">
<h1>Application</h1>
<BrowserRouter>
<Switch>
<Route path="/dashboard">
<Dashboard />
</Route>
<Route path="/preferences">
<Preferences />
</Route>
</Switch>
</BrowserRouter>
</div>
);
}
export default App;
server.js
const express = require('express');
const cors = require('cors')
const app = express();
app.use(cors());
app.use('/login', (req, res) => {
res.send({
token: 'test123'
});
});
app.listen(8080, () => console.log('API is running on http://localhost:4000/login'));

Sending Form Data From Frontend to Backend Using Axios Using React

I am trying to get input from the user in a form field and access the data in my backend server.js . I wanted to use this data in order to pass parameters to the Yelp Fusion API I am using. I know I can use axios for this but am unsure how to accomplish this at this time.
Here is my server.js:
const express = require('express')
const dotenv = require('dotenv').config()
const port = process.env.PORT || 5000
var axios = require('axios');
const app = express()
var cors = require('cors');
app.use(cors());
// app.get('/', (req, res) => {
// var config = {
// method: 'get',
// url: 'https://api.yelp.com/v3/businesses/search?location=Houston',
// headers: {
// 'Authorization': 'Bearer <API_KEY>
// }
// };
// axios(config)
// .then(function (response) {
// //const data = JSON.stringify(response.data);
// res.json(response.data)
// })
// .catch(function (error) {
// console.log(error);
// });
// })
app.listen(port, () => console.log(`Server started on port ${port}`))
Here is the App.js in which I need to pass the state from the input field to the backend:
import React,{useEffect,useState} from 'react';
import './App.css';
import axios from 'axios'
function App() {
const [zip,setZip] = useState("")
function handleSubmit() {
useEffect(() => {
axios.post("http://localhost:8000")
.then(res => {
console.log(res)
})
})
}
// const [results, setResults] = useState({})
// console.log(results)
// useEffect(() => {
// axios.get('http://localhost:8000').then(res => {
// console.log(res)
// })
// }, [])
return (
<div>
<form onSubmit={handleSubmit}>
<label>
Name:
<input type="text" name="name" />
</label>
<input type="submit" value="Submit" />
</form>
</div>
);
}
export default App;
Ok, here's what's wrong with your code:
hooks can only be placed on the first level of functional component (outside any sub-functions) and must be before any return statements.
Use effect will fire on render, in your code it looks like you wanna trigger it on event click.
I would do it this way if I were you:
function App() {
const [zip,setZip] = useState("");
const triggerAPI = useCallback(async () => {
// Use async await instead of chained promise
const res = await axios.post("http://localhost:8000", { zip: zip });
console.log(res)
}, [zip]);
const handleSubmit = useCallback((e) => {
e.preventDefault()
triggerAPI();
}, [triggerAPI])
const handleChange = useCallback((event) => {
setZip(event.target.value);
}, []);
return (
<div>
<form onSubmit={handleSubmit}>
<label>
ZIP:
<input type="text" value={zip} name="zip" onChange={handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
</div>
);
}
export default App;
changes:
I used useCallback to memoize the functions
I used async/await instead of chained promise (looks cleaner)
You use useEffect() function wrongly.
Handle the input element state properly.
To send data to the server you can use axios.post(url,data).then()
import React, { useState } from "react";
import axios from "axios";
function App() {
const [zip, setZip] = useState("");
function handleSubmit(event) {
event.preventDefault();
axios.post("http://localhost:8000", { zip: zip }).then((res) => {
console.log(res);
});
}
const handleChange = (event) => {
setZip(event.target.value);
};
return (
<div>
<form onSubmit={handleSubmit}>
<label>
ZIP:
<input type="text" value={zip} name="zip" onChange={handleChange} />
</label>
<input type="submit" value="Submit" />
</form>
</div>
);
}
export default App;

How to save values sent via post request in redux-toolkit async thunk

I'm making a react component which has two input fields.One have the key : type,another the key: range.The problem is that when i submit the data i dont know how to save it as an array or something,to stack more pairs of information,because i need to display a progress bar based on the information from the input field. Could you help me please?
Here is my Slice:
export const skillSlice = createSlice({
name: "skill",
initialState: {
name:'',
range:null
},
reducers: {
setSkill: (state, action) => {
console.log("action", action.payload);
state.name = action.payload?.name;
state.range = action.payload?.range;
}
}
});
export const addNewSkill = createAsyncThunk(
'skills/addNewSkill',
async (_,{rejectWithValue,dispatch}) =>{
try{
const response = await fetch('/api/skills',{
method:'POST',
headers:{
'Content-name' : 'application/json',
},
});
if(!response.ok){
throw new Error('Can\'t add skill. Server error')
}
const data = await response.json();
dispatch(setSkill(data))
}catch(error){
return rejectWithValue(error.message);
}
}
)
export const fetchSkills = createAsyncThunk(
'skills/fetchSkills',
async (_, {rejectWithValue}) => {
try{
const response = await fetch('/api/skills',{
method:'GET',
})
// console.log(response)
if(!response.ok){
throw new Error ('Server Error!');
}
const data = await response.json();
// console.log(data)
return data;
} catch(error){
return rejectWithValue(error.message);
}
}
);
const { setSkill } = skillSlice.actions;
export const selectSkill = (state) => state?.skill;
export default skillSlice.reducer;
And here is the component:
import React, { useState,useEffect } from 'react'
import { Formik, Form, useFormik } from 'formik'
import * as Yup from 'yup'
import FormikControl from '../Form/FormikControl'
import DisplayFormikState from '../Form/DisplayFormikState.js'
import { useDispatch, useSelector } from 'react-redux'
import { addNewSkill,fetchSkills,selectSkill } from '../../features/skills/skillSlice'
const Skills = () =>{
const dispatch = useDispatch();
const [skill, setSkills] = useState({
name: '',
range: null
});
useEffect(()=>{
dispatch(fetchSkills());
},[dispatch])
const userInfo = useSelector(selectSkill);
const skillList = useSelector(state => state.skillState)
const { status, error } = useSelector(state => state.skillState)
const handleChange = (e) => {
const { name, value } = e.target;
setSkills({ ...skill, [name]: value });
};
const handleSubmit = (e) => {
e.preventDefault();
dispatch(addNewSkill(skill));
};
const formik = useFormik({
// initialValues:{
// name: skill.name,
// range: skill.range
// },
validationSchema:Yup.object({
}),
})
return(
<>
<section id="skills">
<h1 className='SkillSection'>Skills</h1>
<form onSubmit={handleSubmit}>
<div>
<label htmlFor="type">Type</label>
<input
id='type'
name='name'
type='text'
placeholder='Enter skill name'
onChange={handleChange}
// value={formik.values.name}
/>
</div>
<div>
<label htmlFor="level">Level</label>
<input
id='level'
type='text'
name='range'
placeholder='Enter range'
onChange={handleChange}
// value={formik.values.range}
/>
</div>
<button type='submit'>Submit</button>
</form>
</section>
</>
)
}
export default Skills
In the above code the initial state isn't an array because when i tried to push values to it i got undefined,so,i left the working state not to get confused. Thanks in advance!

How can I upload a image file using and react Socket-IO?

i want to make a chat app with react and socket.io
i downloaded code from https://github.com/adrianhajdin/project_chat_application.
I want to add upload file function using socketio_file_upload
but when i upload the img. there is nothing happen..
this is my code
index.js (server)
const express = require('express');
const socketio = require('socket.io');
const http = require('http');
const siofu = require("socketio-file-upload");
const { addUser, removeUser, getUser, getUsersInRoom } = require('./users');
const PORT = process.env.PORT || 5000
const router = require('./router')
const app = express()
console.log(app,'------------------app----------')
const server = http.createServer(app)
const io = socketio(server)
io.on('connection', (socket)=>{
const uploader = new siofu();
uploader.dir = "/uploads";
uploader.listen(socket);
uploader.on("saved", function(event){
});
uploader.on("error", function(event){
});
socket.on('join', ({name, room}, callback)=>{
const { user, error } = addUser({ id:socket.id, name, room })
if(error) {
return callback(error)
}
//admin system정보 여기서
socket.emit('message', { user:'admin', text:`${user.name}, welcome to the room ${user.room}` })
//braodcast는 room에 있는 모든 사람에게 msg를 보낸다.
socket.broadcast.to(user.room).emit('message', { user: 'admin', text: `${user.name} has joined!` });
socket.join(user.room)
io.to(user.room).emit('roomData', {room: user.room, users: getUsersInRoom(user.room)})
callback()
})
socket.on('sendMessage', (message, callback) => {
const user = getUser(socket.id);
io.to(user.room).emit('message', { user: user.name, text: message });
io.to(user.room).emit('roomData', { room: user.room, users: getUsersInRoom(user.room)});
callback();
});
socket.on('disconnect', () => {
const user = removeUser(socket.id)
io.to(user.room).emit('message', { user:'admin', text: `${user.name} has left`})
})
})
app.use(siofu.router)
server.listen(PORT, ()=> console.log('---SERVER START---'))
Chat.jsx
import React, { useState, useEffect, useRef } from 'react';
import queryString from 'query-string'
import io from 'socket.io-client'
import './chat.css'
import InfoBar from '../InfoBar/InfoBar'
import Messages from '../Messages/Messages'
import Input from '../Input/Input'
let socket ='default'
const Chat = ({location}) => {
const [name, setName] = useState('');
const [room, setRoom] = useState('');
const [message, setMessage] = useState('')
const [messages, setMessages] = useState([])
const END_POINT = 'localhost:5000'
//componentdidmount와 같다
useEffect(()=>{
const {name, room} = queryString.parse(location.search)
socket = io(END_POINT)
setName(name)
setRoom(room)
//server에 join을 통해서 데이터를 보냄
socket.emit('join', {name, room}, (res)=>{
})
//useEffect()애서 return 은 unmount와 같다. 즉 user leave일 때 사용!
return () =>{
socket.emit('disconnect')
socket.off()
}
},[END_POINT, location.search])
useEffect(() => {
socket.on('message', (message) =>{
setMessages([...messages, message])
})
// uploader.listenOnInput(document.getElementById("siofu_input"));
}, [messages])
const sendMessage = (event) => {
event.preventDefault();
if(message) {
socket.emit('sendMessage', message, () => setMessage(''));
}
}
return (
<div className="outerContainer">
<div className="container">
<InfoBar room={room} />
<Messages messages={messages} name={name} />
<Input socket={socket} message={message} setMessage={setMessage} sendMessage={sendMessage} />
</div>
</div>
);
};
export default Chat;
Input.jsx
import React, { Component } from 'react';
import SocketIOFileUpload from '../../../../server/node_modules/socketio-file-upload'
import './input.css';
class Input extends Component {
uploadFile = (e) => {
const {socket} = this.props
console.log("uploading");
// const files = e.target.files;
const siofu = new SocketIOFileUpload(socket);
siofu.listenOnInput(document.getElementById("siofu_input"));
};
render() {
const { setMessage, sendMessage, message, socket } = this.props
return (
<form className="form">
<input
className="input"
type="text"
placeholder="Type a message..."
value={message}
onChange={({ target: { value } }) => setMessage(value)}
onKeyPress={event => event.key === 'Enter' ? sendMessage(event) : null}
/>
<input type="file" id="siofu_input" onChange={this.uploadFile.bind(this)}/>
<button className="sendButton" onClick={e => sendMessage(e)}>Send</button>
</form>
);
}
}
export default Input;
users.js
const users = [];
const addUser = ({ id, name, room }) => {
name = name.trim().toLowerCase();
room = room.trim().toLowerCase();
const existingUser = users.find((user) => user.room === room && user.name === name);
if(!name || !room) return { error: 'Username and room are required.' };
if(existingUser) return { error: 'Username is taken.' };
const user = { id, name, room };
users.push(user);
return { user };
}
const removeUser = (id) => {
const index = users.findIndex((user) => user.id === id);
if(index !== -1) return users.splice(index, 1)[0];
}
const getUser = (id) => users.find((user) => user.id === id);
const getUsersInRoom = (room) => users.filter((user) => user.room === room);
module.exports = { addUser, removeUser, getUser, getUsersInRoom };
How can i upload img file to chat app....
At first, you must create "uploads" folder to upload files.
When I run the app on local, I created folder on to D drive and changed uploader.dir from '/uploads' to "uploads";
At second, when you select DOM, you used document.elementById, this is wrong, must use ref={(el)=>this.variable=el} and change to siofu.listenOnInput(this.variable);
At third, you did define upload logic in onChange event listener, have to define in componentDidMount().

Api marvel response don't show react

I try to training in react and want to make a form who call the api marvel when submitted with the current input and display the name + description of the character search.
The Api call is ok but when i submit the form nothing show any advice?
import React, { Component, useEffect, useState } from 'react'
import axios from 'axios'
const SearchEngine = React.forwardRef((props, ref) => {
const [asked, setAsked] = useState([]);
const [characterInfos, setCharacterInfos] = useState([]);
const [searchTerm, setSearchTerm] = useState("");
const [loading, setLoading] = useState(true);
const [inputs, setInputs] = useState('');
const handleChange = (event) => {
setInputs(event.target.value);
console.log(inputs);
}
const getCharacters = (inputs) => {
setSearchTerm(inputs)
axios
.get(`https://gateway.marvel.com:443/v1/public/characters?name=${searchTerm}&apikey=XXX`)
.then(response => {
console.log(searchTerm)
console.log(response)
setCharacterInfos(response.data.data.results[0]);
setLoading(false);
console.log(response.data.data.results[0].name)
response.data.data.results.map((item) => {
return characterInfos.push(item.name)
})
localStorage.setItem(characterInfos, JSON.stringify(response.data))
if (!localStorage.getItem('marvelStorageDate')) {
localStorage.setItem('marvelStorageDate', Date.now());
}
})
.catch(error => {
console.log(error);
})
}
return (
<div className="search-container">
<h1>Character Infos</h1>
<form onSubmit={getCharacters}>
<input
type="text"
placeholder="Search"
value={inputs}
onChange={handleChange}
/>
<input type="submit" value="Envoyer" />
</form>
<ul>
<li>{characterInfos.name}</li>
</ul>
</div>
)
})
export default React.memo(SearchEngine)
Thanks for your help. Any to advice to show a list of all the character and make a search filter who work with minimum 3 characters?
getCharacters is fired with form submit event as param. You are assuming that is getting inputs from the state wrongly:
const getCharacters = event => {
event.preventDefault() // Prevent browser making undesired form native requests
// setSearchTerm(inputs); // Not sure what are you trying here but, again, inputs is a form submit event
axios
.get( // use searchValue as query string in the url
`https://gateway.marvel.com:443/v1/public/characters?name=${searchValue}&apikey=XXX`
)
.then(response => {
console.log(searchTerm);
console.log(response);
setCharacterInfos(response.data.data.results[0]);
setLoading(false);
console.log(response.data.data.results[0].name);
response.data.data.results.map(item => {
return characterInfos.push(item.name);
});
localStorage.setItem(characterInfos, JSON.stringify(response.data));
if (!localStorage.getItem("marvelStorageDate")) {
localStorage.setItem("marvelStorageDate", Date.now());
}
})
.catch(error => {
console.log(error);
});
};

Resources