Loading set to true, reducer dispatch stuck at request after few renders of application. Need to re-run every time it stuck like this [closed] - node.js

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed yesterday.
Improve this question
Creating a react application with nodejs backend power with redux for state management. After i run my application for few renders all the dispatches are running as it supposed to be but after a point...loading is set true forever. I need to re-run the application from commandline and again same issue. would like to know what's the problem.
My UserActions:
import axios from 'axios'
import { BOT_DETAILS_RESET, BOT_LIST_RESET } from '../constants/botConstants'
import { USER_CREATE_FAILURE, USER_CREATE_REQUEST, USER_CREATE_SUCCESS, USER_DELETE_FAILURE, USER_DELETE_REQUEST, USER_DELETE_SUCCESS, USER_DETAILS_FAILURE, USER_DETAILS_REQUEST, USER_DETAILS_RESET, USER_DETAILS_SUCCESS, USER_LIST_FAILURE, USER_LIST_REQUEST, USER_LIST_RESET, USER_LIST_SUCCESS, USER_LOGIN_FAILURE, USER_LOGIN_REQUEST, USER_LOGIN_SUCCESS, USER_LOGOUT, USER_UPDATE_FAILURE, USER_UPDATE_REQUEST, USER_UPDATE_SUCCESS } from "../constants/userConstants"
export const login = (username, password) => async (dispatch) => {
try {
dispatch({
type: USER_LOGIN_REQUEST
})
const config = {
header: {
'Content-Type': 'application/json',
}
}
const { data } = await axios.post('/api/users/login', { username, password }, config)
dispatch({
type: USER_LOGIN_SUCCESS,
payload: data
})
localStorage.setItem('userInfo', JSON.stringify(data))
} catch (error) {
dispatch({
type: USER_LOGIN_FAILURE,
payload: error.response && error.response.data.message ? error.response.data.message : error.message
})
}
}
export const listUsers = () => async (dispatch, getState) => {
try {
dispatch({
type: USER_LIST_REQUEST
})
const { userLogin: { userInfo } } = getState()
const config = {
headers: {
Authorization: `Bearer ${userInfo.token}`
}
}
const { data } = await axios.get(`/api/users`, config)
console.log(data)
dispatch({
type: USER_LIST_SUCCESS,
payload: data.users_list
})
} catch (error) {
const message =
error.response && error.response.data.message
? error.response.data.message
: error.message
if (message === 'Not authorized, token failed') {
dispatch(logout())
}
dispatch({ type: USER_LIST_FAILURE, payload: message })
}
}
export const deleteUser = (username) => async (dispatch, getState) => {
try {
dispatch({
type: USER_DELETE_REQUEST
})
const { userLogin: { userInfo } } = getState()
const config = {
headers: {
Authorization: `Bearer ${userInfo.token}`
}
}
await axios.delete(`/api/users/${username}`, config)
dispatch({
type: USER_DELETE_SUCCESS,
})
} catch (error) {
const message = error.response && error.response.data.message ? error.response.data.message : error.message
if (message === 'Not authorized, token failed') {
dispatch(logout())
}
dispatch({ type: USER_DELETE_FAILURE, payload: message })
}
}
export const createUser = (first_name, last_name, username, password, role) => async (dispatch, getState) => {
const newRole = role.toUpperCase()
console.log(newRole)
try {
dispatch({
type: USER_CREATE_REQUEST
})
const { userLogin: { userInfo } } = getState()
const config = {
headers: {
Authorization: `Bearer ${userInfo.token}`
}
}
const { data } = await axios.post(`/api/users/`, { first_name, last_name, username, password, role: newRole }, config)
console.log(data)
dispatch({
type: USER_CREATE_SUCCESS,
payload: data
})
} catch (error) {
dispatch({ type: USER_CREATE_FAILURE, payload: error.response && error.response.data.message ? error.response.data.message : error.message })
}
}
export const getUserDetails = (username) => async (dispatch, getState) => {
try {
dispatch({
type: USER_DETAILS_REQUEST
})
const { userLogin: { userInfo } } = getState()
const config = {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${userInfo.token}`
}
}
const { data } = await axios.get(`/api/users/${username}`, config)
dispatch({
type: USER_DETAILS_SUCCESS,
payload: data
})
} catch (error) {
const message =
error.response && error.response.data.message
? error.response.data.message
: error.message
if (message === 'Not authorized, token failed') {
dispatch(logout())
}
dispatch({ type: USER_DETAILS_FAILURE, payload: message })
}
}
export const updateUser = (user, username) => async (dispatch, getState) => {
try {
dispatch({
type: USER_UPDATE_REQUEST
})
const { userLogin: { userInfo } } = getState()
const config = {
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${userInfo.token}`
}
}
const { data } = await axios.put(`/api/users/${username}`, user, config)
dispatch({
type: USER_UPDATE_SUCCESS,
})
dispatch({
type: USER_DETAILS_SUCCESS,
payload: data
})
} catch (error) {
const message =
error.response && error.response.data.message
? error.response.data.message
: error.message
if (message === 'Not authorized, token failed') {
dispatch(logout())
}
dispatch({ type: USER_UPDATE_FAILURE, payload: message })
}
}
export const logout = () => (dispatch) => {
localStorage.removeItem('userInfo')
dispatch({ type: USER_DETAILS_RESET })
dispatch({ type: BOT_DETAILS_RESET })
dispatch({ type: USER_LIST_RESET })
dispatch({ type: BOT_LIST_RESET })
dispatch({ type: USER_LOGOUT })
document.location.href = '/'
}
My user Reducer:
export const userLoginReducer = (state = {}, action) => {
switch (action.type) {
case USER_LOGIN_REQUEST:
return { loading: true }
case USER_LOGIN_SUCCESS:
return { loading: false, userInfo: action.payload }
case USER_LOGIN_FAILURE:
return { loading: false, error: action.payload }
case USER_LOGOUT:
return {}
default:
return state
}
}
export const userListReducer = (state = { users: [] }, action) => {
switch (action.type) {
case USER_LIST_REQUEST:
return { loading: true, }
case USER_LIST_SUCCESS:
return { loading: false, users: action.payload }
case USER_LIST_FAILURE:
return { loading: false, error: action.payload }
case USER_LIST_RESET:
return { users: [] }
default:
return state
}
}
export const userDeleteReducer = (state = {}, action) => {
switch (action.type) {
case USER_DELETE_REQUEST:
return { loading: true, }
case USER_DELETE_SUCCESS:
return { loading: false, success: true }
case USER_DELETE_FAILURE:
return { loading: false, error: action.payload }
default:
return state
}
}
export const userCreateReducer = (state = {}, action) => {
switch (action.type) {
case USER_CREATE_REQUEST:
return { loading: true, }
case USER_CREATE_SUCCESS:
return { loading: false, success: true, user: action.payload }
case USER_CREATE_FAILURE:
return { loading: false, error: action.payload }
case USER_CREATE_RESET:
return {}
default:
return state
}
}
export const userDetailsReducer = (state = { user: {} }, action) => {
switch (action.type) {
case USER_DETAILS_REQUEST:
return { ...state, loading: true, }
case USER_DETAILS_SUCCESS:
return { loading: false, user: action.payload }
case USER_DETAILS_FAILURE:
return { loading: false, error: action.payload }
case USER_DETAILS_RESET:
return { user: {} }
default:
return state
}
}
export const userUpdateReducer = (state = { user: {} }, action) => {
switch (action.type) {
case USER_UPDATE_REQUEST:
return { loading: true, }
case USER_UPDATE_SUCCESS:
return { loading: false, success: true }
case USER_UPDATE_FAILURE:
return { loading: false, error: action.payload }
case USER_UPDATE_RESET:
return { user: {} }
default:
return state
}
}
My Login Component:
import React, { useEffect, useState } from 'react'
import COLOR from '../const/colors'
import { Row, Col, Space, Typography, Form, Button, Input } from 'antd'
import { Link, useNavigate } from 'react-router-dom'
import { useDispatch, useSelector } from 'react-redux'
import { login } from '../redux/actions/userActions'
const { Title } = Typography
const LoginPage = () => {
const dispatch = useDispatch()
const navigate = useNavigate()
const [input, setInput] = useState({
username: '',
password: ''
})
const userLogin = useSelector(state => state.userLogin)
const { loading, userInfo, error } = userLogin
const handleChange = (e) => {
const { name, value } = e.target
setInput({
...input,
[name]: value
})
}
const onFinishFailed = (errorInfo) => {
console.log('Failed:', errorInfo);
};
const handleSubmit = () => {
dispatch(login(input.username, input.password))
console.log('login request dispatched')
}
useEffect(() => {
if (userInfo) {
navigate('/auth')
}
}, [userInfo, dispatch, navigate])
return (
<div>
{loading && <p>Loading...</p>}
{error && <p>{error}</p>}
<Row gutter={[0, { xs: 8, sm: 16, md: 24, lg: 32 }]}>
<Col className="gutter-row"
xs={{ span: 20, offset: 2 }}
sm={{ span: 16, offset: 4 }}
md={{ span: 14, offset: 6 }}
lg={{ span: 14, offset: 6 }}
xl={{ span: 6, offset: 9 }}>
<Row justify="center" align="middle">
<Col span={24}>
<Space direction="vertical" className="container-login">
<Title level={4}
style={{
color: COLOR.PRIMARY,
textAlign: "center",
fontWeight: "bold",
marginTop: 20,
}}>
Sign in to Damex CWC
</Title>
<br />
<Form
name="normal-login"
className='login-form'
onFinish={handleSubmit}
onFinishFailed={onFinishFailed}
autoComplete="off"
>
{/* <Spin
spinning={loading}
size="large"
indicator={
<LoadingOutlined style={{ color: "#00ff6a" }} />
}
> */}
<Form.Item
rules={[
{
required: true,
message: "Please input your Username"
},
{
type: "username",
message: "Please enter a valid email address",
},
]}
>
<Input
name='username'
size="large"
placeholder={"Username"}
value={input.username}
onChange={handleChange}
/>
</Form.Item>
<Form.Item
rules={[
{
required: true,
message: "Please input your Password",
},
]}
>
<Input.Password
name='password'
size="large"
placeholder={"Password"}
value={input.password}
onChange={handleChange}
/>
</Form.Item>
{/* <Form.Item
name="remember"
valuePropName="checked"
>
<Checkbox>Remember me</Checkbox>
</Form.Item> */}
<Form.Item
>
<Button
block
type="primary"
htmlType="submit"
className="login-form-button"
>
Sign In
</Button>
</Form.Item>
{/* </Spin> */}
</Form>
</Space>
</Col>
</Row>
<br />
<Row
justify="center" align="middle"
>
<Button
className="link-login"
type="link"
>
<Link className='link-login' to={"/forgotpassword"}>
Forgot password?
</Link>
</Button>
<span>{"‧"}</span>
<Button
className="link-login"
type="link"
>
<Link className='link-login' to={"#"}
onClick={(e) => {
window.location = "mailto:info#damex.io";
e.preventDefault();
}}
>
Don't have an account?
</Link>
</Button>
<span>{"‧"}</span>
<Button type="link" className="link-login" >
<Link
className="link-login"
to="https://www.damex.io/privacy"
target="_blank"
rel="noopener noreferrer"
>
Privacy Policy
</Link>
</Button>
</Row>
<Row justify="center" align="middle">
<Link to="mailto:support#damex.io?subject=Issue with 2FA (Damex Business)">
<Button type="link" className="link-login">
Have an issue with 2-factor authentication?
</Button>
</Link>
</Row>
</Col>
</Row>
</div>
)
}
export default LoginPage
My userList page:
import { Button, Col, Row } from 'antd'
import React, { useEffect, useState, } from 'react'
import COLOR from '../const/colors'
import { useDispatch, useSelector } from 'react-redux'
import { useNavigate } from 'react-router-dom'
import { deleteUser, listUsers } from '../redux/actions/userActions'
import Table from '../components/Table'
import ModalDelete from '../components/ModalDelete'
const UserListPage = () => {
const dispatch = useDispatch()
const navigate = useNavigate()
const userLogin = useSelector(state => state.userLogin)
const { userInfo } = userLogin
console.log(userInfo.role)
const userList = useSelector(state => state.userList)
const { loading, error, users } = userList
const userDelete = useSelector(state => state.userDelete)
const { success: successDelete } = userDelete
const [selectedUser, setSelectedUser] = useState(null);
const [modalVisible, setModalVisible] = useState(false);
const handleCreate = () => {
navigate(`/auth/users/create`)
};
useEffect(() => {
if ((userInfo && (userInfo.role === 'ADMIN' || userInfo.role === 'TRADING'))) {
dispatch(listUsers())
} else {
navigate('/')
}
}, [dispatch, userInfo, successDelete, navigate])
// handle delete button click
const handleDelete = (user) => {
setSelectedUser(user);
setModalVisible(true);
};
// handle modal confirm delete
const handleConfirmDelete = () => {
// dispatch delete user by username action
dispatch(deleteUser(selectedUser.username));
setModalVisible(false);
};
// handle modal cancel delete
const handleCancelDelete = () => {
setSelectedUser(null);
setModalVisible(false);
};
return (
<div style={{ padding: '0 1rem' }}>
{userInfo && (userInfo.role === 'ADMIN' || userInfo.role === 'TRADING') ? (
<>
<div style={{ color: COLOR.SECONDARY_TEXT, marginBottom: '32px', marginTop: '24px' }}>
Users
</div>
<Row style={{ margin: '24px' }}>
<Col offset={20}>
<Button type='primary' onClick={handleCreate} className='create-btn'>Create User</Button>
</Col>
</Row>
<Table users={users} handleDelete={handleDelete} />
{loading && <p>Loading...{loading}</p>}
{error && <p>{error}</p>}
</>
) :
<p>Not Authorized to view this</p>
}
<ModalDelete
user={selectedUser}
isModalOpen={modalVisible}
onConfirm={handleConfirmDelete}
onCancel={handleCancelDelete}
/>
</div>
)
}
export default UserListPage
Table component:
import React from 'react'
import { Table as AntdTable, Button, Space } from 'antd'
import { useNavigate } from 'react-router-dom';
const Table = ({ users, bots, handleDelete }) => {
console.log(users && users)
console.log(bots && bots)
const navigate = useNavigate()
const handleEdit = (record) => {
users && navigate(`/auth/users/${record.username}`);
bots && navigate(`/auth/bots/${record.bot_id}`);
};
let columns = [];
if (users) {
columns = [{ key: 'username', title: 'Username', dataIndex: 'username' }, { key: 'role', title: 'Role', dataIndex: 'role' }]
} else if (bots) {
columns = [
{ key: 'bot_id', title: 'BotID', dataIndex: 'bot_id' },
{ key: 'exchange', title: 'Exchange', dataIndex: 'exchange' },
{ key: 'strategy', title: 'Strategy', dataIndex: 'strategy' },
{ key: 'trading_pair', title: 'Trading Pair', dataIndex: 'trading_pair' },
]
}
const actionColumn = {
title: 'Action',
dataIndex: 'id',
key: 'action',
render: (id, record) => (
<Space size={'large'}>
<Button type="primary" onClick={() => handleEdit(record)}>Edit</Button>
<Button type="primary" className='danger-btn' onClick={() => handleDelete(record)}>Delete</Button>
</Space>
),
};
const tableColumns = [
...columns,
actionColumn,
];
return (
<AntdTable rowKey={record => users ? record.username : record.bot_id} dataSource={users ? users : bots} columns={tableColumns} />
)
}
export default Table
I couldn't figure out what's wrong...if it's problem with front end it shouldn't be working with starting few renders of application right. In case backend controller here it is:
import asyncHandler from 'express-async-handler'
import generateToken from '../utils/generateToken.js'
import pool from '../config/db.js'
import bcrypt from 'bcryptjs'
//Auth user & get token
// Post /api/users/login
// Public route
export const authUser = asyncHandler(async (req, res) => {
console.log('logging...')
const { username, password } = req.body
try {
const query = `SELECT * FROM users WHERE username = '${username}';`
const client = await pool.connect()
const user = await client.query(query);
client.release();
if (user.rows.length !== 0) {
const user_info = user.rows[0];
const matchedPassword = await bcrypt.compare(password, user_info.password);
if (matchedPassword) {
res.status(200).json({
username: user_info.username,
role: user_info.role,
token: generateToken(user_info.username)
});
} else {
res.status(401).json({ message: 'Invalid email or password! Please, try again' });
}
} else {
res.status(401).json({ message: 'Invalid email or password! Please, try again' });
}
} catch (error) {
res.status(500).json({ message: 'Server error has occurred', error: error })
}
})
// //get user profile
// // GET /api/users/profile
// // Private route
export const getUserProfile = asyncHandler(async (req, res) => {
try {
const user_profile_query = `SELECT username, first_name, last_name, role FROM users WHERE username = '${req.username}';`
const client = await pool.connect();
const results = await client.query(user_profile_query);
client.release();
if (results.rows.length !== 0) {
const user_profile = results.rows[0]
res.status(200).json({ user_profile });
}
else {
res.status(404).json({ message: `User Not Found for ${req.username}` });
}
} catch (error) {
res.status(500).json({ message: `Internal Server Error while fetching user - ${req.username}.`, error: error })
}
})
// //put update user password
// // PUT /api/users/profile
// // Private route
export const updateUserPassword = asyncHandler(async (req, res) => {
try {
const updatedHashedPassword = await bcrypt.hash(req.body.password, 10);
const user_password_update_query = `UPDATE users SET password = '${updatedHashedPassword}' WHERE username = '${req.username}' RETURNING username, first_name, last_name, role;`
const client = await pool.connect();
const results = await client.query(user_password_update_query);
client.release();
if (results.rows.length !== 0) {
const user_password_update = results.rows[0]
res.status(200).json({ user_password_update });
}
else {
res.status(404).json({ message: `User Not Found for ${req.username}` });
}
} catch (error) {
res.status(500).json({ message: `Internal Server Error while updating password for user - ${req.username}.`, error: error })
}
})
//Register a new user
// Post /api/users
// Private/Admin route
export const registerUser = asyncHandler(async (req, res) => {
console.log('registering...')
try {
const { username, first_name, last_name, password, role } = req.body
const user_exist_query = `SELECT * FROM users WHERE username = '${username}';`
const client = await pool.connect();
const user_exists = await client.query(user_exist_query);
if (user_exists.rows.length !== 0) {
return res.status(400).json({ message: `User - ${username} already exists.` })
}
const hashedPassword = await bcrypt.hash(password, 10);
const user_register_query = 'INSERT INTO users (username, first_name, last_name, password, role) VALUES ($1, $2, $3, $4, $5) RETURNING username, first_name, last_name, role;';
const values = [username, first_name, last_name, hashedPassword, role]
const results = await client.query(user_register_query, values);
client.release();
if (results.rows.length !== 0) {
const user_info = results.rows[0];
res.status(201).json({
username: user_info.username,
role: user_info.role,
})
} else {
res.status(400).json({ message: `Invalid user data for registering user - ${username}` })
}
} catch (error) {
res.status(500).json({ message: `Internal Server Error while registering user - ${username}.`, error: error })
}
})
//get all users
// GET /api/users
// Private/admin route
export const getUsers = asyncHandler(async (req, res) => {
try {
const users_list_query = `SELECT username, first_name, last_name, role FROM users;`
const client = await pool.connect();
const results = await client.query(users_list_query);
client.release();
if (results.rows.length !== 0) {
const users_list = results.rows
res.status(200).json({ users_list });
}
else {
res.status(404).json({ message: `No users found.` });
}
} catch (error) {
res.status(500).json({ message: `Internal Server Error while fetching users list}.`, error: error })
}
})
//delete a user by id
// delete /api/users/:id
// Private/admin route
export const deleteUser = asyncHandler(async (req, res) => {
try {
const user_delete_query = `DELETE FROM users WHERE username = '${req.params.username}';`
const client = await pool.connect();
const user_delete = await client.query(user_delete_query);
client.release();
if (user_delete.rowCount !== 0) {
res.status(200).json({ message: 'User removed from Database successfully.' });
}
else {
res.status(404).json({ message: `User Not Found for ${req.params.username}` });
}
} catch (error) {
res.status(500).json({ message: `Internal Server Error while deleting user - ${req.params.username}.`, error: error })
}
})

Related

React/Postgres sql detail: 'Failing row contains (43, ccc, null, 0, 2022-07-01 15:37:11.631)

**I am getting the error when I am connecting the frontend code as well as backend code with the database maybe the problem might be in front end but pls let me know the meaning of the error because I am newbie.I am getting the error on register pls help me and also when I register the website using frontend it shows me error on **localhost/register
enter image description here
const express = require('express');
const { listen } = require('express/lib/application');
const bodyParser=require('body-parser');
const bcrypt=require('bcrypt-nodejs')
const cors = require('cors')
const knex = require('knex');
const { response } = require('express');
const db=knex({
client: 'pg',
connection: {
host : '127.0.0.1',
user : 'postgres',
password : '224898',
database : 'smart-brain'
}
});
const app = express();
app.use(bodyParser.json());
app.use(cors())
const database={
users:[
{
id:'123',
name:'John',
email:'John#gmail.com',
password:'ABC',
entries:0,
joined:new Date()
},
{
id:'124',
name:'ABC',
email:'ABC',
password:'123',
entries:0,
joined:new Date()
}
],
login:[
{
id:'987',
hash:'',
email:'John#gmail.com'
}
]
}
app.get('/' ,(req,res)=>{
res.send(database.users);
})
app.post('/signin',(req,res)=>{
if(req.body.email===database.users[0].email && req.body.password===database.users[0].password){
res.json(database.users[0]);
}else{
res.status(400).json('error login in');
}
})
app.post('/register',(req,res)=>{
const{email,name,password}=req.body;
db('users')
.returning('*')
.insert({
email:email,
name:name,
joined: new Date()
})
.then(user=>{
res.json(user[0]);
})
. catch(err => console.log(err))
})
app.get('/profile/:id',(req,res)=>{
const{id}=req.params;
let found=false;
database.users.forEach(user=>{
if(user.id===id){
found=true;
return res.json(user);
}
})
if(!found){
res.status(400).json('not found');
}
})
app.put('/image',(req,res)=>{
const{id}=req.body;
let found=false;
database.users.forEach(user=>{
if(user.id===id){
found=true;
user.entries++
return res.json(user.entries);
}
})
if(!found){
res.status(400).json('not found');
}
})
// // Load hash from your password DB.
// bcrypt.compare("bacon", hash, function(err, res) {
// // res == true
// });
// bcrypt.compare("veggies", hash, function(err, res) {
// // res = false
// });
app.listen(3000,()=>{
console.log('app is running on port 3000 ');
})
AND ALSO I AM SHARING FRONTEND APP.JS CODE
APP.js code
import './App.css';
import Navigation from './Components/Navigation/Navigation';
import FaceRecognition from './Components/FaceRecognition/FaceRecognition';
import Logo from './Components/Logo/Logo'
import ImageLinkForm from './Components/ImageLinkForm/ImageLinkForm'
import Rank from './Components/Rank/Rank'
import { Component } from 'react';
import Particles from "react-tsparticles";
import { loadFull } from "tsparticles";
import SignIn from './Components/SignIn/SignIn';
import Register from './Components/Register/Register'
const USER_ID = 'aad';
const PAT = 'bd69e06e68f244ed83b9ce09ee560e7c';
const APP_ID = 'aaa';
const MODEL_ID = 'face-detection';
const MODEL_VERSION_ID = '45fb9a671625463fa646c3523a3087d5';
const particlesOption = {
fpsLimit: 120,
particles: {
links: {
color: "#ffffff",
distance: 150,
enable: true,
opacity: 0.5,
width: 1,
},
collisions: {
enable: true,
},
move: {
direction: "none",
enable: true,
outModes: {
default: "bounce",
},
random: true,
speed: 5,
straight: true,
},
},
detectRetina: true,
}
const particlesInit = async (main) => {
await loadFull(main);
};
const initialState = {
input: '',
imageUrl: '',
box: {},
route:'signin',
isSignedIn:false,
user: {
id: '',
name: '',
email: '',
joined: '',
entries: 0
}
};
class App extends Component {
constructor() {
super();
this.state = initialState;
};
loadUser = (data) => {
this.setState({
user: {
id: data.id,
name: data.name,
email: data.email,
entries: data.entries,
joined: data.joined
}
})
}
apiData = () => {
const raw = JSON.stringify({
"user_app_id": {
"user_id": USER_ID,
"app_id": APP_ID
},
"inputs": [
{
"data": {
"image": {
"url": this.state.input
}
}
}
]
});
const requestOptions = {
method: 'POST',
headers: {
'Accept': 'application/json',
'Authorization': 'Key ' + PAT
},
body: raw
};
return requestOptions;
}
displayFaceBox = (box) => {
this.setState({ box: box });
}
onInputChange=(event) =>{
this.setState({input: event.target.value});
}
onImageSubmit = () => {
this.setState({ imageUrl: this.state.input });
const requestOptions = this.apiData();
fetch("https://api.clarifai.com/v2/models/" + MODEL_ID + "/versions/" + MODEL_VERSION_ID + "/outputs", requestOptions)
.then(response => response.text())
.then(result => JSON.parse(result))
.then(obj => {
if (obj) {
fetch('http://localhost:3000/image', {
method: 'put',
headers: {'content-type': 'application/json'},
body: JSON.stringify({
id: this.state.user.id
})
})
.then(response => response.json())
.then(count => {
this.setState(Object.assign(this.state.user, {entries: count}))
})
}
this.displayFaceBox(this.calculateFaceLocation(obj))
})
.catch(error => console.log('error', error));
}
calculateFaceLocation = (data) => {
const clarifaiFace = data.outputs[0].data.regions[0].region_info.bounding_box;
const image = document.getElementById('inputimage');
const width = Number(image.width);
const height = Number(image.height);
return ({
leftCol: clarifaiFace.left_col * width,
topRow: clarifaiFace.top_row * height,
rightCol: width - (clarifaiFace.right_col * width),
bottomRow: height - (clarifaiFace.bottom_row * height),
})
}
onRouteChange=(route)=>{
if(route==='signout'){
this.setState({isSignedIn:false})
}else if(route==='home'){
this.setState({isSignedIn:true})
}
this.setState({route:route})
}
render(){
const { imageUrl, box ,isSignedIn,route} = this.state;
return (
<div className="App">
<Particles className='particles'
init={particlesInit}
options={particlesOption}
/>
<Navigation isSignedIn={isSignedIn} onRouteChange={this.onRouteChange} />{ route==='home'?
<div>
<Logo />
<Rank name={this.state.user.name} entries={this.state.user.entries}/>
<ImageLinkForm onInputChange={this.onInputChange}
onImageSubmit={this.onImageSubmit}/>
<FaceRecognition box={box} imageUrl={imageUrl} />
</div> :(
route==='signin'?
<SignIn loadUser={this.loadUser} onRouteChange={this.onRouteChange} />
: <Register loadUser={this.loadUser}onRouteChange={this.onRouteChange}/>
)
}
</div>
);
}
}
export default App;
Do not use images for textual information, copy and paste the text into the question. This would make the following easier.
From error message code:23502. If you go here Error codes you find that corresponds to 23502 not_null_violation. So the value that is being set to NULL is being entered into a column that has NOT NULL set. Your choices are:
a) Make sure the value is not set to NULL.
b) If you can have NULL values in the column drop the NOT NULL constraint.

Have a Handler Change Value of a Variable in Mongodb

I am working on a product where I have pre orders and normal orders. For my pre order items, I have the variable pre_orderQty, and for my normal items, I have the variable qty. In my OrderScreen.js, I have a handler that deals with if an order has been shipped (shipHandler). The issue that I am having is that I am trying to get this handler to also update any items in my order that have a qty value of 0 to the value of the pre_orderQty when clicked.
I am using node in my backend and react in my frontend. The orders are stored in mongodb. I'm not exactly sure how to do this, and I would really appreciate any help or advice on how to accomplish this.
So far, I have attempted to do this by:
In my backend orderRouter.js
orderRouter.put(
'/:id/updated',
isAuth,
isAdmin,
expressAsyncHandler(async (req, res) => {
const order = await Order.findById(req.params.id);
if (order && order.orderItems.qty === 0) {
order.orderItems.qty = order.orderItems.pre_orderQty;
order.orderItems.pre_orderQty = 0;
const updatedOrder = await order.save();
res.send({ message: 'Order Updated', order: updatedOrder });
} else {
res.status(404).send({ message: 'Order Not Found' });
}
}),
);
Frontend:
OrderActions.js
export const updateOrder = (orderId) => async (dispatch, getState) => {
dispatch({ type: ORDER_UPDATE_REQUEST, payload: orderId });
const {
userSignin: { userInfo },
} = getState();
try {
const { data } = Axios.put(
`/api/orders/${orderId}/updated`,
{},
{
headers: { Authorization: `Bearer ${userInfo.token}` },
},
);
dispatch({ type: ORDER_UPDATE_SUCCESS, payload: data });
} catch (error) {
const message = error.response && error.response.data.message ? error.response.data.message : error.message;
dispatch({ type: ORDER_UPDATE_FAIL, payload: message });
}
};
OrderScreen
import Axios from 'axios';
import { PayPalButton } from 'react-paypal-button-v2';
import React, { useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Link } from 'react-router-dom';
import {shipOrder, deliverOrder, detailsOrder, payOrder, updateOrder } from '../actions/orderActions';
import LoadingBox from '../components/LoadingBox';
import MessageBox from '../components/MessageBox';
import {
ORDER_DELIVER_RESET,
ORDER_SHIPPED_RESET,
ORDER_RETURN_RESET,
ORDER_PAY_RESET,
} from '../constants/orderConstants';
export default function OrderScreen(props) {
const orderId = props.match.params.id;
const [sdkReady, setSdkReady] = useState(false);
const orderDetails = useSelector((state) => state.orderDetails);
const { order, loading, error } = orderDetails;
const userSignin = useSelector((state) => state.userSignin);
const { userInfo } = userSignin;
const orderShip = useSelector((state) => state.orderShip);
const {
loading: loadingShip,
error: errorShip,
success: successShip,
} = orderShip;
const orderUpdate = useSelector((state) => state.orderUpdate);
const {
loading: loadingUpdate,
error: errorUpdate,
success: successUpdate,
} = orderUpdate;
const dispatch = useDispatch();
useEffect(() => {
if (
!order ||
successShip ||
successUpdate ||
(order && order._id !== orderId)
) {
dispatch({ type: ORDER_SHIPPED_RESET });
dispatch({ type: ORDER_UPDATE_RESET });
dispatch(detailsOrder(orderId));
} else {
if (!order.isPaid) {
if (!window.paypal) {
addPayPalScript();
} else {
setSdkReady(true);
}
}
}
}, [dispatch, order, orderId, sdkReady, successShip, successUpdate, order]);
const shipHandler = () => {
dispatch(shipOrder(order._id));
dispatch(updateOrder(order._id));
};
return loading ? (
<LoadingBox></LoadingBox>
) : error ? (
<MessageBox variant="danger">{error}</MessageBox>
) : (
<div>
<h1>Order {order._id}</h1>
<div className="row top">
<div className="col-1">
<div className="card card-body">
<ul>
{userInfo.isAdmin && (
<li>
{loadingShip && <LoadingBox></LoadingBox>}
{errorShip && (
<MessageBox variant="danger">{errorShip}</MessageBox>
)}
<button
type="button"
className="primary block"
onClick={shipHandler}
>
Order Shipped
</button>
</li>
)}
</ul>
</div>
</div>
</div>
</div>
);
}

POST http://localhost:3000/api/devolucions 400 (Bad Request)

I'm pretty new to javascript, and I'm trying to create a page to return orders for an e-commerce website that I'm creating. I want a customer to be able to start a return when they click the Return Order button on their orders history page. When I click on the Return Order button I'm getting a POST http://localhost:3000/api/devolucions 400 (Bad Request). This post is created in the backend in devolucionRoute.js and called in the frontend in devolucionActions.js. I'm unsure why I am getting this error, and I would really appreciate any help or guidance on how to fix this issue.
Thank you!
Note: devolucion is the name that I used in place of return
devolucionActions.js
import Axios from 'axios';
import {
DEVOLUCION_CREATE_FAIL,
DEVOLUCION_CREATE_REQUEST,
DEVOLUCION_CREATE_SUCCESS,
DEVOLUCION_DETAILS_FAIL,
DEVOLUCION_DETAILS_REQUEST,
DEVOLUCION_DETAILS_SUCCESS,
DEVOLUCION_SUMMARY_REQUEST,
DEVOLUCION_SUMMARY_SUCCESS,
} from '../constants/devolucionConstants';
export const createDevolucion = (devolucion) => async (dispatch, getState) => {
dispatch({ type: DEVOLUCION_CREATE_REQUEST, payload: devolucion });
try {
const {
userSignin: { userInfo },
} = getState();
const { data } = await Axios.post('/api/devolucions', devolucion, {
headers: {
Authorization: `Bearer ${userInfo.token}`,
},
});
dispatch({ type: DEVOLUCION_CREATE_SUCCESS, payload: data.devolucion });
} catch (error) {
dispatch({
type: DEVOLUCION_CREATE_FAIL,
payload:
error.response && error.response.data.message
? error.response.data.message
: error.message,
});
}
};
export const detailsDevolucion = (devolucionId) => async (dispatch, getState) => {
dispatch({ type: DEVOLUCION_DETAILS_REQUEST, payload: devolucionId });
const {
userSignin: { userInfo },
} = getState();
try {
const { data } = await Axios.get(`/api/devolucions/${devolucionId}`, {
headers: { Authorization: `Bearer ${userInfo.token}` },
});
dispatch({ type: DEVOLUCION_DETAILS_SUCCESS, payload: data });
} catch (error) {
const message =
error.response && error.response.data.message
? error.response.data.message
: error.message;
dispatch({ type: DEVOLUCION_DETAILS_FAIL, payload: message });
}
};
export const summaryDevolucion = () => async (dispatch, getState) => {
dispatch({ type: DEVOLUCION_SUMMARY_REQUEST });
const {
userSignin: { userInfo },
} = getState();
try {
const { data } = await Axios.get('/api/devolucions/summary', {
headers: { Authorization: `Bearer ${userInfo.token}` },
});
dispatch({ type: DEVOLUCION_SUMMARY_SUCCESS, payload: data });
} catch (error) {
dispatch({
type: DEVOLUCION_CREATE_FAIL,
payload:
error.response && error.response.data.message
? error.response.data.message
: error.message,
});
}
};
Backend
devolucionRouter.js
import express from 'express';
import expressAsyncHandler from 'express-async-handler';
import Order from '../models/orderModel.js';
import Devolucion from '../models/devolucionModel.js';
import User from '../models/userModel.js';
import Product from '../models/productModel.js';
import {isAdmin, isAuth, isSellerOrAdmin} from '../utils.js';
const devolucionRouter = express.Router();
devolucionRouter.get(
'/mine',
isAuth,
expressAsyncHandler(async (req, res) => {
const devolucion= await Devolucion.find({ user: req.user._id });
res.send(devolucion);
})
);
devolucionRouter.post(
'/',
isAuth,
expressAsyncHandler(async (req, res) => {
if (req.body.devolucionItems.length === 0) {
res.status(400).send({ message: 'No Return' });
} else {
const devolucion = new Devolucion({
seller: req.body.orderItems[0].seller,
orderItems: req.body.orderItems,
devolucionItems: req.body.devolucionItems,
shippingAddress: req.body.shippingAddress,
paymentMethod: req.body.paymentMethod,
itemsPrice: req.body.itemsPrice,
itemsProfit: req.body.itemsProfit,
shippingPrice: req.body.shippingPrice,
taxPrice: req.body.taxPrice,
totalPrice: req.body.totalPrice,
totalProfit: req.body.totalProfit,
user: req.user._id,
});
const createdDevolucion = await devolucion.save();
res
.status(201)
.send({ message: 'New Return Created', devolucion: createdDevolucion });
}
})
);
devolucionRouter.get(
'/:id',
isAuth,
expressAsyncHandler(async (req, res) => {
const devolucion = await Devolucion.findById(req.params.id);
if (devolucion) {
res.send(devolucion);
} else {
res.status(404).send({ message: 'Return Not Found' });
}
})
);
export default devolucionRouter;
server.js
import express from 'express';
import mongoose from 'mongoose';
import dotenv from 'dotenv';
import path from 'path';
import userRouter from './routers/userRouter.js';
import productRouter from './routers/productRouter.js';
import orderRouter from './routers/orderRouter.js';
import devolucionRouter from './routers/devolucionRouter.js';
import uploadRouter from './routers/uploadRouter.js';
dotenv.config();
const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: true }));
mongoose.connect(process.env.MONGODB_URL || 'mongodb://localhost/AM', {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
});
app.use('/api/uploads', uploadRouter);
app.use('/api/users', userRouter);
app.use('/api/products', productRouter);
app.use('/api/orders', orderRouter);
app.use('/api/devolucions', devolucionRouter);
app.get('/api/config/paypal', (req, res) => {
res.send(process.env.PAYPAL_CLIENT_ID || 'sb');
});
const __dirname = path.resolve();
app.use('/uploads', express.static(path.join(__dirname, '/uploads')));
app.get('/', (req, res) => {
res.send('Server is ready');
});
app.use((err, req, res, next) => {
res.status(500).send({ message: err.message });
});
const port = process.env.PORT || 5000;
app.listen(port, () => {
console.log(`Serve at http://localhost:${port}`);
});
OrderHistoryScreen.js (Frontend)
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { listOrderMine, detailsOrder } from '../actions/orderActions';
import LoadingBox from '../components/LoadingBox';
import MessageBox from '../components/MessageBox';
import {createDevolucion } from '../actions/devolucionActions';
import { DEVOLUCION_CREATE_RESET } from '../constants/devolucionConstants';
export default function OrderHistoryScreen(props) {
const orderId = props.match.params.id;
const order = useSelector((state) => state.order);
const devolucionCreate = useSelector((state) => state.devolucionCreate);
const {success, devolucion } = devolucionCreate;
const orderMineList = useSelector((state) => state.orderMineList);
const { loading, error, orders } = orderMineList;
const dispatch = useDispatch();
useEffect(() => {
dispatch(listOrderMine());
dispatch(detailsOrder(orderId));
}, [dispatch, orderId]);
const placeDevolucionHandler = () => {
dispatch(createDevolucion({ ...order, devolucionItems: order.orderItems }));
};
useEffect(() => {
if (success) {
props.history.push(`/devolucion/${devolucion._id}`);
dispatch({ type: DEVOLUCION_CREATE_RESET });
}
}, [dispatch, devolucion, props.history, success]);
return (
<div>
<h1>Order History</h1>
{loading ? (
<LoadingBox></LoadingBox>
) : error ? (
<MessageBox variant="danger">{error}</MessageBox>
) : (
<table className="table">
<thead>
<tr>
<th>ACTIONS</th>
</tr>
</thead>
<tbody>
{orders.map((order) => (
<tr key={order._id}>
<td>
<button
type="button"
onClick={placeDevolucionHandler}
className="small"
// disabled={cart.cartItems.length === 0}
>
Return Order
</button>
</td>
</tr>
))}
</tbody>
</table>
)}
</div>
);
}
devolucionReducer.js (Frontend)
import {
DEVOLUCION_CREATE_FAIL,
DEVOLUCION_CREATE_REQUEST,
DEVOLUCION_CREATE_RESET,
DEVOLUCION_CREATE_SUCCESS,
DEVOLUCION_DETAILS_FAIL,
DEVOLUCION_DETAILS_REQUEST,
DEVOLUCION_DETAILS_SUCCESS,
DEVOLUCION_DELETE_REQUEST,
DEVOLUCION_DELETE_SUCCESS,
DEVOLUCION_DELETE_FAIL,
DEVOLUCION_DELETE_RESET,
DEVOLUCION_SUMMARY_REQUEST,
DEVOLUCION_SUMMARY_SUCCESS,
DEVOLUCION_SUMMARY_FAIL,
} from '../constants/devolucionConstants';
export const devolucionCreateReducer = (state = {}, action) => {
switch (action.type) {
case DEVOLUCION_CREATE_REQUEST:
return { loading: true };
case DEVOLUCION_CREATE_SUCCESS:
return { loading: false, success: true, devolucion: action.payload };
case DEVOLUCION_CREATE_FAIL:
return { loading: false, error: action.payload };
case DEVOLUCION_CREATE_RESET:
return {};
default:
return state;
}
};
export const devolucionDetailsReducer = (
state = { loading: true },
action
) => {
switch (action.type) {
case DEVOLUCION_DETAILS_REQUEST:
return { loading: true };
case DEVOLUCION_DETAILS_SUCCESS:
return { loading: false, devolucion: action.payload };
case DEVOLUCION_DETAILS_FAIL:
return { loading: false, error: action.payload };
default:
return state;
}
};
export const devolucionDeleteReducer = (state = {}, action) => {
switch (action.type) {
case DEVOLUCION_DELETE_REQUEST:
return { loading: true };
case DEVOLUCION_DELETE_SUCCESS:
return { loading: false, success: true };
case DEVOLUCION_DELETE_FAIL:
return { loading: false, error: action.payload };
case DEVOLUCION_DELETE_RESET:
return {};
default:
return state;
}
};
export const devolucionSummaryReducer = (
state = { loading: true, summary: {} },
action
) => {
switch (action.type) {
case DEVOLUCION_SUMMARY_REQUEST:
return { loading: true };
case DEVOLUCION_SUMMARY_SUCCESS:
return { loading: false, summary: action.payload };
case DEVOLUCION_SUMMARY_FAIL:
return { loading: false, error: action.payload };
default:
return state;
}
};
store.js (frontend)
import { createStore, compose, applyMiddleware, combineReducers } from 'redux';
import thunk from 'redux-thunk';
import { cartReducer } from './reducers/cartReducers';
import {
devolucionCreateReducer,
devolucionDeleteReducer,
devolucionShipReducer,
devolucionDeliverReducer,
devolucionDetailsReducer,
devolucionListReducer,
devolucionMineListReducer,
devolucionPayReducer,
devolucionSummaryReducer,
} from './reducers/devolucionReducers';
import {
orderCreateReducer,
orderDeleteReducer,
orderShipReducer,
orderDeliverReducer,
orderDetailsReducer,
orderListReducer,
orderMineListReducer,
orderPayReducer,
orderSummaryReducer,
orderReducer,
} from './reducers/orderReducers';
import {
productCategoryListReducer,
productCreateReducer,
productDeleteReducer,
productDetailsReducer,
productListReducer,
productReviewCreateReducer,
productUpdateReducer,
} from './reducers/productReducers';
const initialState = {
userSignin: {
userInfo: localStorage.getItem('userInfo')
? JSON.parse(localStorage.getItem('userInfo'))
: null,
},
cart: {
cartItems: localStorage.getItem('cartItems')
? JSON.parse(localStorage.getItem('cartItems'))
: [],
shippingAddress: localStorage.getItem('shippingAddress')
? JSON.parse(localStorage.getItem('shippingAddress'))
: {},
paymentMethod: 'PayPal',
},
};
const reducer = combineReducers({
devolucionCreate: devolucionCreateReducer,
devolucionDetails: devolucionDetailsReducer,
devolucionDelete: devolucionDeleteReducer,
devolucionSummary: devolucionSummaryReducer,
productList: productListReducer,
productDetails: productDetailsReducer,
cart: cartReducer,
order: orderReducer,
userSignin: userSigninReducer,
userRegister: userRegisterReducer,
orderCreate: orderCreateReducer,
orderDetails: orderDetailsReducer,
orderPay: orderPayReducer,
orderMineList: orderMineListReducer,
orderSummary: orderSummaryReducer,
userDetails: userDetailsReducer,
userUpdateProfile: userUpdateProfileReducer,
userUpdate: userUpdateReducer,
productCreate: productCreateReducer,
productUpdate: productUpdateReducer,
productDelete: productDeleteReducer,
orderList: orderListReducer,
orderDelete: orderDeleteReducer,
orderShip: orderShipReducer,
orderDeliver: orderDeliverReducer,
productReviewCreate: productReviewCreateReducer,
userList: userListReducer,
userDelete: userDeleteReducer,
productCategoryList: productCategoryListReducer,
});
const composeEnhancer = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
reducer,
initialState,
composeEnhancer(applyMiddleware(thunk))
);
export default store;

Why do I have to refresh the page when I delete a post? MERN stack

I am a beginner in the MERN stack and I am interested in why I have to refresh the page after deleting the document (post)?
This is my Action.js
export const deletePost = id => async (dispatch, getState) => {
try {
dispatch({ type: DELETE_POST_BEGIN });
const {
userLogin: { userInfo },
} = getState();
const config = {
headers: {
Authorization: `Bearer ${userInfo.token}`,
},
};
const { data } = await axios.delete(`/api/v1/post/${id}`, config);
dispatch({ type: DELETE_POST_SUCCESS, payload: data });
} catch (error) {
dispatch({
type: DELETE_POST_FAIL,
payload: { msg: error.response.data.msg },
});
}
};
This is my Reducer.js
export const deletePostReducer = (state = {}, action) => {
switch (action.type) {
case DELETE_POST_BEGIN:
return { loading: true };
case DELETE_POST_SUCCESS:
return { loading: false };
case DELETE_POST_FAIL:
return { loading: false, error: action.payload.msg };
default:
return state;
}
};
And this is my Home page where i list all posts:
import { useEffect } from 'react';
import { Col, Container, Row } from 'react-bootstrap';
import { useDispatch, useSelector } from 'react-redux';
import { getPosts } from '../actions/postActions';
import Loader from '../components/Loader';
import Message from '../components/Message';
import Post from '../components/Post';
const HomePage = () => {
const dispatch = useDispatch();
const allPosts = useSelector(state => state.getPosts);
const { loading, error, posts } = allPosts;
const deletePost = useSelector(state => state.deletePost);
const { loading: loadingDelete } = deletePost;
useEffect(() => {
dispatch(getPosts());
}, [dispatch]);
return (
<Container>
{loading || loadingDelete ? (
<Loader />
) : error ? (
<Message variant='danger'>{error}</Message>
) : (
<>
<Row>
{posts.map(post => (
<Col lg={4} key={post._id} className='mb-3'>
<Post post={post} />
</Col>
))}
</Row>
</>
)}
</Container>
);
};
export default HomePage;
And this is my single Post component:
const Post = ({ post }) => {
const dispatch = useDispatch();
const allPosts = useSelector(state => state.getPosts);
const { loading, error, posts } = allPosts;
const userLogin = useSelector(state => state.userLogin);
const { userInfo } = userLogin;
const handleDelete = id => {
dispatch(deletePost(id));
};
return (
<>
<div>{post.author.username}</div>
<Card>
<Card.Img variant='top' />
<Card.Body>
<Card.Title>{post.title}</Card.Title>
<Card.Text>{post.content}</Card.Text>
<Button variant='primary'>Read more</Button>
{userInfo?.user._id == post.author._id && (
<Button variant='danger' onClick={() => handleDelete(post._id)}>
Delete
</Button>
)}
</Card.Body>
</Card>
</>
);
};
And my controller:
const deletePost = async (req, res) => {
const postId = req.params.id;
const post = await Post.findOne({ _id: postId });
if (!post.author.equals(req.user.userId)) {
throw new BadRequestError('You have no permission to do that');
}
await Post.deleteOne(post);
res.status(StatusCodes.NO_CONTENT).json({
post,
});
};
I wish someone could help me solve this problem, it is certainly something simple but I am a beginner and I am trying to understand.
I believe the issue is that you are not fetching the posts after delete is successful.
Try this inside the HomePage component:
...
const [isDeleting, setIsDeleting] = useState(false);
const { loading: loadingDelete, error: deleteError } = deletePost;
useEffect(() => {
dispatch(getPosts());
}, [dispatch]);
useEffect(() => {
if (!deleteError && isDeleting && !loadingDelete) {
dispatch(getPosts());
}
setIsDeleting(loadingDelete);
}, [dispatch, deleteError, isDeleting, loadingDelete]);
...
Another method is to use "filtering", but you have to update your reducer as such:
export const deletePostReducer = (state = {}, action) => {
switch (action.type) {
case DELETE_POST_BEGIN:
return { loading: true };
case DELETE_POST_SUCCESS:
return { loading: false, data: action.payload}; // <-- this was changed
case DELETE_POST_FAIL:
return { loading: false, error: action.payload.msg };
default:
return state;
}
};
Now in your HomePage component, you will do something like this when rendering:
...
const { loading: loadingDelete, data: deletedPost } = deletePost;
...
useEffect(() => {
dispatch(getPosts());
if (deletedPost) {
console.log(deletedPost);
}
}, [dispatch, deletedPost]);
return (
...
<Row>
{posts.filter(post => post._id !== deletedPost?._id).map(post => (
<Col lg={4} key={post._id} className='mb-3'>
<Post post={post} />
</Col>
))}
</Row>
)

how to update context state in react

I am having a problem that when user upload their profile image it did not change, user have to log out and log back in to make a change complete.
Here is my back end how to get image from client and store it on cloudinary:
profilesController.js:
exports.updateAvatar = async (req, res) => {
// Find user with matching token
// const updates = [];
const updateUserAvatar = await models.User.findOne({
where: {
id: req.id,
},
});
// Was user found?
if (updateUserAvatar === null) {
return res.status(200).json({
validationErrors: {
errors: [
{
msg: "Reset is invalid or has expired.",
},
],
},
});
}
// Update user with new info
models.User.update(
{
picture: req.imageUrl,
},
{
where: {
id: updateUserAvatar.dataValues.id,
},
}
);
console.log(updateUserAvatar);
At the console it should gave me a new image url but instead it just keep the old image url
Here is my profilesAPI where my route is:
router.post('/upload/image', function (req, res, next) {
const dUri = new Datauri();
const dataUri = (req) => dUri.format(path.extname(req.name).toString(), req.data);
if (req.files !== undefined && req.files !== null) {
const { file, id } = req.files;
const newFile = dataUri(file).content;
cloudinary.uploader.upload(newFile)
.then(result => {
const imageUrl = result.url;
const data = {id : req.body.id, imageUrl };
updateAvatar(data);
return res.status(200).json({ message: 'Success', data: { imageUrl } });
}).catch(err => res.status(400).json({message:'Error', data: { err}}));
} else {
return res.status(400).json({ message: 'Error' });
}
});
And that's all for my back end code. Here is my front end that cient send image to server:
Here is the method that help user can send image to server:
const UserCard = ({ name, userEmail, isVerified, id, updateUserAvatar, currentUser }) => {
const [selectedValue, setSelectedValue] = useState("a");
const handleChange = (event) => {
setSelectedValue(event.target.value);
};
const [imageSelected, setImageSelected] = useState("");
const uploadImage = () => {
const formData = new FormData();
formData.append("file", imageSelected);
formData.append("id", id);
axios
.post("/api/v1/profiles/upload/image", formData, {
headers: { "Content-Type": "multipart/form-data" },
})
.then((response) => {
updateUserAvatar(response.data.data.imageUrl);
});
};
useEffect(() => {
if (imageSelected !== '') {
uploadImage();
}
}, [imageSelected]);
return (
<div className="avatar--icon_profile">
<Card className="profile--card_container">
<CardContent>
{currentUser.picture ? (
<div>
<input
className="my_file"
type="file"
ref={inputFile}
onChange={(e) => setImageSelected(e.target.files[0])}
/>
<div className="profile-image">
<Avatar
src={currentUser.picture}
alt="Avatar"
className="avatar--profile_image"
onClick={onButtonClick}
/>
</div>
</div>
and here is my Global State. I tried to update nested state in my context but seems like it didn't work.
const GlobalState = (props) => {
// User State -----------------------------------------------------------------------------
const [currentUser, setUser] = useState(props.serverUserData);
console.log(currentUser)
const updateUser = (userData) => {
setUser(userData);
};
// This method is passed through context to update currentUser Avatar
const updateUserAvatar = (picture) => {
setUser({ ...currentUser, picture: picture });
};
const providerValues = {
currentUser,
updateUser,
updateUserAvatar,
};
return (
<GlobalContext.Provider value={providerValues}>
{props.children}
</GlobalContext.Provider>
);
};
export default GlobalState;
and here is my console.log(currentUser) gave me:
{id: "a19cac5c-ea25-4c9c-b1d9-5d6e464869ed", name: "Nhan Nguyen", email: "nhan13574#gmail.com", publicId: "Nh1615314435848", picture: "http://res.cloudinary.com/teammateme/image/upload/v1617229506/gnlooupiekujkrreerxn.png", …}
email: "nhan13574#gmail.com"
id: "a19cac5c-ea25-4c9c-b1d9-5d6e464869ed"
isSessionValid: true
name: "Nhan Nguyen"
picture: "http://res.cloudinary.com/teammateme/image/upload/v1617229506/gnlooupiekujkrreerxn.png"
publicId: "Nh1615314435848"
__proto__: Object
Can anyone help me solve this problem? I really appreciate it
Added GlobalContext.js:
import React from "react";
const globalStateDefaults = {
modals: {
isAuthModalOpen: false,
modalToDisplay: "signup",
toggleModal: () => {},
setModalToDisplay: () => { },
},
user: undefined,
pageName: undefined,
loading: false,
teamProfileId: "",
userProfileId: "",
};
export const GlobalContext = React.createContext(globalStateDefaults);
You need to consume the context where you are trying to update user state.
const {currentUser, updateUser, updateUserAvatar} = React.useContext(GlobalContext)
Then you can call
updateUserAvatar(response.data.data.imageUrl)

Resources