I have app with devices-array which have objects
with device_name and device_id. I'd like to remove specific device depending which device user want's to remove from devices array.
I've already tryied to findIndex and indexOf -methods, but it return's undefined for request. How to access device depending which device user want's to remove?
deviceController.js
'use strict'
import Users from '../models/userModel.js'
deleteDevice: async (req, res) => {
try {
const { device } = req.body.device.device_id
const dev = await Users.findOne({ _id: req.user.id }).populate('device')
const devs = dev.device //devices
const index = devs.findIndex(req.body.device)
const devic = devs.slice(index, 1)
await Users.findOneAndUpdate({ _id: req.user.id }, { device: devic })
res.json({ msg: 'Deleted success' })
} catch (err) {
return res.status(500).json({ msg: err.message })
}
}
export { deviceControl }
import React, { useState, useEffect } from 'react'
import { Link } from 'react-router-dom'
import axios from 'axios'
import { useSelector, useDispatch } from 'react-redux'
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome'
import { faEdit, faTrash } from '#fortawesome/free-solid-svg-icons'
import { Container, Table } from 'react-bootstrap'
import { showErr, showSuccess } from '../utils/notifications/Notification'
import {
fetchAllUsers,
dispatchGetAllUsers
} from '../../redux/actions/usersAction'
import '../../index.css'
//initialize device
const initialState = {
device: { device_name: '', _id: '', device_id: '' },
err: '',
success: ''
}
function AllDevices() {
//authentication
const auth = useSelector((state) => state.auth)
//token
const token = useSelector((state) => state.token)
//set data
const [data, setData] = useState(initialState)
//users
const users = useSelector((state) => state.users)
const { device_name, device_id, err, success } = data
//loading
const [loading, setLoading] = useState(false)
//authentication
const { user, isAdmin } = auth
const dispatch = useDispatch()
const handleChange = (e) => {
const { name, value } = e.target
setData({ ...data, [name]: value, err: '', success: '' })
}
useEffect(() => {
if (isAdmin) {
fetchAllUsers(token).then((res) => {
dispatch(dispatchGetAllUsers(res))
})
}
if (isAdmin || user) {
setData(initialState)
}
}, [token, user, isAdmin, dispatch, loading])
const updateDeviceName = async () => {
try {
if (window.confirm('Are you sure you want to rename this device?')) {
await axios.patch(
`/device/edit/${data.device._id}/${data.device.device_name}`,
{
device: { device_name, device_id }
},
{
headers: { Authorization: token }
}
)
}
setData({ ...data, err: '', success: 'Updated Success!' })
} catch (err) {
setData({ ...data, err: err.response.data.msg, success: '' })
}
}
const handleUpdate = () => {
if (device_name) updateDeviceName(device_name)
}
const handleDelete = async () => {
try {
if (window.confirm('Are you sure you want to delete this device?')) {
setLoading(true)
await axios.patch(
`/device/delete/${data.device}`,
{ device: data.device },
{
headers: { Authorization: token }
}
)
}
setData({ ...data, err: '', success: 'Updated Success!' })
} catch (err) {
setData({ ...data, err: err.response.data.msg, success: '' })
}
}
return (
<>
<h5 className='m-5'>
{' '}
<Link to='/'>
<i className='fas fa-undo-alt'></i>Takaisin
</Link>
</h5>
<Container fluid='sm'>
<div>
{err && showErr(err)}
{success && showSuccess(success)}
{loading && <h3>Loading.....</h3>}
</div>
<Table bordered hover variant='light' responsive>
<tbody>
<tr>
<th>Nimi</th>
<th>Laite</th>
</tr>
{/* Loop through user details */}
{users.map((p) => (
<tr>
<td>
{p.name}
<br />
{p.email}
</td>
<td>
{p.device.map((d) => (
<div>
<div
className='d-flex-inline'
style={{
position: 'relative',
width: '170px'
}}
>
{' '}
<input
type='text'
style={{
fontSize: '16px',
width: '100px'
}}
defaultValue={d.device_name}
name='device_name'
onChange={handleChange}
/>{' '}
<FontAwesomeIcon
style={{
position: 'absolute',
top: '3px',
right: '70px',
zIndex: '2'
}}
icon={faEdit}
title='Edit'
onClick={() => handleUpdate(d.device_name)}
/>{' '}
</div>
<div
className='d-flex'
style={{
position: 'relative',
width: '100px'
}}
>
<input
type='text'
style={{
fontSize: '14px',
width: '200px',
color: '#333'
}}
defaultValue={d.device_id}
disabled
name='device_id'
/>{' '}
<FontAwesomeIcon
style={{
position: 'absolute',
top: '3px',
right: '3px',
zIndex: '2'
}}
icon={faTrash}
title='Trash'
onClick={() => handleDelete(d.device)}
/>{' '}
</div>
</div>
))}
</td>
</tr>
))}
</tbody>
</Table>
</Container>
</>
)
}
export default AllDevices
const deviceSchema = mongoose.Schema({
device_id: { type: Number, required: true },
device_name: { type: String, required: true }
})
const userSchema = new mongoose.Schema(
{
name: {
type: String,
required: [true, 'Please enter your name!']
},
email: {
type: String,
required: [true, 'Please enter your email!']
},
device: [deviceSchema, { type: mongoose.Schema.Types.ObjectId }],
password: {
type: String,
required: [true, 'Please enter your password!']
},
days: { type: Date },
role: {
type: Number,
default: 0 // 0 = user 1= admin 3=visitor
}
},
{
timestamps: true
}
)
const Users = mongoose.model('User', userSchema)
export default Users
import { deviceControl } from '../controllers/deviceController.js'
import express from 'express'
import auth from '../middleware/auth.js'
import authAdmin from '../middleware/authAdmin.js'
const router = express.Router()
router.get('/device', auth, authAdmin, deviceControl.getUsersAllDevices)
router.post('/device', auth, authAdmin, deviceControl.getUsersAllDevices)
router.patch('/device/delete/:id', auth, authAdmin, deviceControl.deleteDevice)
router.put('/add_device', auth, deviceControl.addDevice)
router.patch('/device/edit', auth, deviceControl.updateDeviceName)
export default router
try using JS filter function.
const removeDevice(devices, id) => {
return devices.filter(device => device.id !== id)
}
Related
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 })
}
})
Server
The server prints the groups
I am Trying to retrieve all groups from my Mongodb database but the value keeps returning as undefined.
I am creating a react app but i might be getting confused with Aync and how to use the promise
router.get('/groups', async (req, res) => {
try {
const groups = await Group.find().sort({ date: -1 });
res.json(groups);
console.log(groups);
} catch (err) {
console.error(err.message);
res.status(500).send('Server Error');
}
});
Actions
i cant also see the groups being printed here
export const getAllGroups = () => async (dispatch) => {
axios
.get("/api/group/groups")
.then(res =>
dispatch({
type: GET_GROUPS,
payload: res.payload.data
})
)
.catch(err =>
dispatch({
type: GET_GROUPS,
payload: null
})
);
};
Component
this is where i keep getting the undefined when i try to use groups.
class GroupList extends Component {
componentDidMount() => {
const {groups} = await this.props.getAllGroups();
this.props.getAllGroups(groups)
}
// Delete account
onDeleteClick = id => {
const { groups } = this.props;
const groupData = {
id: id,
groups: groups
};
this.props.deleteGroup(groupData);
};
render() {
const { user, groups } = this.props;
let groupItems = groups.map(group => (
<li key={group._id} style={{ marginTop: "1rem" }}>
<button
style={{ marginRight: "1rem" }}
onClick={this.onDeleteClick.bind(this, group._id)}
className="btn btn-small btn-floating waves-effect waves-light hoverable red accent-3"
>
<i className="material-icons">delete</i>
</button>
<b>{group.name}</b>
</li>
));
return (
<div>
<Link to="/" className="btn-flat waves-effect">
<i className="material-icons left">keyboard_backspace</i> Back to
home
</Link>
{ { <ul>{groupItems}</ul> } }
</div>
)
}
}
GroupList.propTypes = {
logoutUser: PropTypes.func.isRequired,
getAllGroups: PropTypes.func.isRequired,
// addAccount: PropTypes.func.isRequired,
deleteGroup: PropTypes.func.isRequired,
groups: PropTypes.array.isRequired,
// plaid: PropTypes.object.isRequired,
user: PropTypes.object.isRequired
};
const mapStateToProps = state => ({
groups: state.groups
});
export default connect(
mapStateToProps,
{ getAllGroups, deleteGroup }
)(GroupList);
1.After I came to profile page that show my profile details my console log shows POST http://localhost:3000/profileEdit 500 (Internal Server error)
2.I change my activity drinks about topics and then refresh page it shows nothing like it didn't save at all except image
I debug by myself then tried to find solution in reddit, quora, stackoverflow 5 day but can't find it So please could you help me a bit
this is frontend
import React, { useState, useEffect } from "react";
import { connect } from "react-redux";
import { useCookies } from "react-cookie";
import { Link } from "react-router-dom";
import axios from "axios";
import {
ref, uploadBytesResumable, getDownloadURL, getStorage
} from "firebase/storage";
import { profileInit } from "../redux/action";
import "./profileEdit.css";
import styled from "styled-components";
const Avatar = styled.div`
width: 250px;
height: 250px;
border-radius: 50%;
background-size: cover;
background-position: center;
cursor: pointer;
`;
function ProfileEdit(props) {
const [cookies, removeCookies] = useCookies([
"userName",
"userNickname",
]);
const [activity, setActivity] = useState("");
const [drinks, setDrinks] = useState("");
const [topics, setTopics] = useState("");
const [about, setAbout] = useState("");
const [url, setUrl] = useState("./images/UploadPic.svg");
const [save, setSave] = useState("");
const id = cookies.userName;
const { profileInit, user } = props;
const [image, setImage] = useState(null);
function patchData(event) {
event.preventDefault();
axios
.patch("/users/profile", {
activity,
drinks,
topics,
about,
id,
})
.then(({ data }) => {
if (data.success) {
setSave("Changes were saved");
} else {
setSave(data.err);
}
});
const storage = getStorage();
const storageRef = ref(storage, `images/${cookies.userName || "./images/infoUser.svg"}`);
const uploadTask = uploadBytesResumable(storageRef, image);
uploadTask.on("state_changed", undefined, undefined, () => {
getDownloadURL(storageRef).then((url) => {
setUrl(url);
});
});
if (setUrl !== null || setUrl == null) {
axios
.patch("/users/profile", {
activity,
drinks,
topics,
about,
id,
avatar: url,
})
.then(({ data }) => {
if (data.success) {
setSave("Saved");
} else {
setSave(data.err);
}
});
}
}
function handleChangeAbout(event) {
event.preventDefault();
setAbout(event.target.value);
}
function handleChangeDrinks(event) {
event.preventDefault();
setDrinks(event.target.value);
}
function handleChangeTopics(event) {
event.preventDefault();
setTopics(event.target.value);
}
function handleChangeActivity(event) {
event.preventDefault();
setActivity(event.target.value);
}
function LogOut() {
user.id = null;
removeCookies("userName");
removeCookies("userNickname");
}
useEffect(() => {
const storage = getStorage();
getDownloadURL(ref(storage, `images/${cookies.userName}`))
.then((url) => {
setUrl(url);
});
axios
.post('/users/profileEdit', {
id,
})
.then(({ data }) => {
setActivity(data.profileId.activity);
setDrinks(data.profileId.drinks);
setAbout(data.profileId.about);
setTopics(data.profileId.topics);
profileInit(data.profileId);
});
}, [profileInit, id]);
function photoDownload(e) {
if (e.target.files[0]) {
setImage(e.target.files[0]);
const storage = getStorage();
const storageRef = ref(storage, `images/${cookies.userName}`);
const uploadTask = uploadBytesResumable(storageRef, image);
uploadTask.on(
"state_changed",
() => {
setUrl("./loading.gif");
},
(error) => {
console.log(error);
},
() => {
getDownloadURL(storageRef)
.then((url) => {
setUrl(url);
});
},
);
}
}
return (
<>
<div className="profile-container">
<div style={{ alignSelf: "center" }}>
<label htmlFor="file-input">
<Avatar style={{ backgroundImage: `url(${url})` }} />
</label>
<input id="file-input" type="file" onChange={photoDownload} />
</div>
<form onSubmit={patchData} className="edit">
<span
style={{ textShadow: "none", marginBottom: "8px", color: "#fff" }}
>
Activity:
</span>
<label>
<input
value={activity}
onChange={handleChangeActivity}
type="text"
name="activity"
className="profileInput"
required
/>
</label>
<span
style={{ textShadow: "none", marginBottom: "8px", color: "#fff" }}
>
Topics:
</span>
<label>
<input
value={topics}
onChange={handleChangeTopics}
type="text"
name="topics"
className="profileInput"
required
/>
</label>
<span
style={{ textShadow: "none", marginBottom: "8px", color: "#fff" }}
>
About:
</span>
<label>
<input
value={about}
onChange={handleChangeAbout}
type="text"
name="about"
className="profileInput"
required
/>
</label>
<span
style={{ textShadow: "none", marginBottom: "8px", color: "#fff" }}
>
Drinks:
</span>
<label>
<input
value={drinks}
onChange={handleChangeDrinks}
type="text"
name="drinks"
className="profileInput"
required
/>
</label>
<button
style={{ margin: "0 auto" }}
className="chatButton"
>
{" "}
Save changes
{" "}
</button>
<div style={{ marginTop: "15px", color: "#fff" }}>
{" "}
{save}
</div>
</form>
<div className="quitEdit" style={{ margin: "0 auto" }}>
<Link to="/listUsers" style={{ position: "relative" }}>
<img src="./images/back.svg" width="100" height="100" alt="BackToListPage" title="BackToListPage" />
</Link>
</div>
<div className="exit" style={{ margin: "0 auto" }}>
<Link to="/login" onClick={LogOut} style={{ position: "relative" }}>
<img src="./images/exit.svg" width="100" height="100" alt="Logout" title="Logout" />
</Link>
</div>
</div>
</>
);
}
const mapStateToProps = (state) => ({
profileId: state.user.profileId,
user: state.user,
err: state.error,
});
const mapDispatchToProps = (dispatch) => ({
profileInit: (profileId) => dispatch(profileInit(profileId)),
});
export default connect(mapStateToProps, mapDispatchToProps)(ProfileEdit);
my backend code for /users/profile and /users/profileEdit
router.patch('/profile', async (req, res) => {
const {
activity,
topics,
about,
drinks,
avatar,
id,
} = req.body;
const response = await Profile.updateOne({ person: id }, {
activity, topics, about, drinks, avatar
});
if (response) {
res.send({ success: true });
} else {
res.send({ success: false, err: 'Try again' });
}
});
router.post('/profileEdit', async (req, res) => {
const { id } = req.body;
const response = await Profile.findOne({ person: id });
if (response) {
res.send({ profileId: response });
} else {
res.status(500).send({ err: 'Something went wrong' });
}
});
Edit post here -> modelProfile.js
const mongoose = require('mongoose');
const profileSchema = new mongoose.Schema({
person: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Person',
},
name: {
type: String,
required: true,
minlength: 1,
},
DoB: {
type: Date,
required: true,
},
activity: {
type: String,
required: true,
minlength: 1,
},
about: {
type: String,
minlength: 1,
},
topics: String,
drinks: String,
avatar: String,
latitude: Number,
longitude: Number,
},
{
versionKey: false,
});
module.exports = mongoose.model('Profile', profileSchema);
here is process page
import React, { useState } from "react";
import axios from "axios";
import { LogIn } from "../redux/action";
import { connect } from "react-redux";
import ImageUpload from "./PhotoUpload";
import { useNavigate } from "react-router-dom";
import { FromProcess, FromProcessContainer, ButtonCreate } from "./CreatingElements";
function CreatingAccount (props) {
const navigate = useNavigate();
const [state,setState] = useState({
currentStep: 1,
name: "",
DoB: "",
activity: "",
topics: "",
drinks: "",
about: ""
});
const handleChange = e => {
const { name, value } = e.target;
setState(state => ({
...state, // <-- copy previous state
[name]: value, // <-- update property
}));
};
const handleSubmit = async e => {
e.preventDefault();
const { user } = props;
let { name, DoB, activity, topics, drinks, about } = state;
await axios.post("/users/profile", {
name,
DoB,
activity,
topics,
drinks,
about,
id: user.id
});
const profileId = {
person: user.id,
name,
DoB,
activity,
about,
topics,
drinks
};
props.LogIn(user.id, user.nickname, profileId);
navigate("/listUsers");
};
const _next = () => {
let currentStep = state.currentStep;
currentStep = currentStep >= 2 ? 3 : currentStep + 1;
setState(state => ({
...state, // <-- copy previous state
currentStep: currentStep// <-- update property
}));
};
const _prev = () => {
let currentStep = state.currentStep;
currentStep = currentStep <= 1 ? 1 : currentStep - 1;
setState(state => ({
...state, // <-- copy previous state
currentStep: currentStep// <-- update property
}));
};
function previousButton() {
let currentStep = state.currentStep;
if (currentStep !== 1) {
return (
<>
<ButtonCreate
style={{ color: "#3103ff" }}
className="btn"
type="button"
onClick={_prev}
>
Previous
</ButtonCreate>
<br />
</>
);
}
return null;
}
function nextButton() {
let currentStep = state.currentStep;
if (currentStep < 3) {
return (
<ButtonCreate
className="btn"
type="button"
onClick={_next}
data-cy="next-process"
style={{
marginBottom: "25px",
color: "#FFF",
backgroundColor: "#3103ff"
}}
>
Next
</ButtonCreate>
);
}
return null;
}
return (
<>
<FromProcessContainer>
<FromProcess onSubmit={handleSubmit} >
<p>Step {state.currentStep}</p>
<br/>
<Step1
currentStep={state.currentStep}
handleChange={handleChange}
name={state.name}
DoB={state.DoB}
activity={state.activity}
/>
<Step2
currentStep={state.currentStep}
handleChange={handleChange}
topics={state.topics}
drinks={state.drinks}
/>
<Step3
currentStep={state.currentStep}
handleChange={handleChange}
about={state.about}
/>
{previousButton()}
{nextButton()}
</FromProcess>
</FromProcessContainer>
</>
);
}
function Step1(props) {
if (props.currentStep !== 1) {
return null;
}
return (
<div className="form-group">
<label>
<input
value={props.name}
onChange={props.handleChange}
type="text"
name="name"
placeholder="Your name"
required
data-cy="input-name-process"
/>
</label>
<label>
<input
value={props.DoB}
onChange={props.handleChange}
type="date"
name="DoB"
placeholder="Date of Birth"
max="2010-01-01"
min="1930-12-31"
required
data-cy="input-Dob-process"
/>
</label>
<label>
<input
value={props.activity}
onChange={props.handleChange}
type="text"
name="activity"
required
placeholder="Place of work or study (required)"
data-cy="input-activity-process"
/>
</label>
</div>
);
}
function Step2(props) {
if (props.currentStep !== 2) {
return null;
}
return (
<div className="form-group">
<label>
<input
value={props.topics}
onChange={props.handleChange}
type="text"
name="topics"
placeholder="Favorite topics: (Optional)"
/>
</label>
<label>
<input
type="text"
value={props.drinks}
onChange={props.handleChange}
name="drinks"
placeholder="Favorite drink: (Optional)"
/>
</label>
</div>
);
}
function Step3(props) {
if (props.currentStep !== 3) {
return null;
}
return (
<>
<ImageUpload/>
<div className="form-group">
<label>
<input
value={props.about}
onChange={props.handleChange}
className="form-control"
type="text"
name="about"
placeholder="Caption (Optional)"
/>
</label>
</div>
<button
type="submit"
className="btn"
data-cy="submit-process"
style={{
backgroundColor: "#3103ff",
marginBottom: "25px",
color: "#FFF"
}}
>
Save it
</button>
</>
);
}
const mapStateToProps = state => ({
user: state.user
});
const mapDispatchToProps = dispatch => ({
LogIn: (id, nickname, profileId) => dispatch(LogIn(id, nickname, profileId))
});
export default connect(mapStateToProps, mapDispatchToProps)(CreatingAccount);
backend for /process
router.post('/profile', async (req, res) => {
const {
name,
DoB,
activity,
topics,
about,
drinks,
avatar,
id,
} = req.body;
const user = await Person.findOne({ _id: id }).exec();
if (!user.profileId) {
const newProfile = await Profile.create({
person: id,
name,
DoB,
activity,
topics,
about,
drinks,
avatar,
});
await Person.updateOne(user, { $set: { profileId: newProfile._id } });
return res.send({
success: true,
});
}
await Person.updateOne({ _id: user.profileId }, {
$set: {
activity,
topics,
about,
drinks,
avatar,
},
});
});
In your axios post, add a .then and a .catch, console.log() the result of the post whether its a success or a failure, also, not sure if u have the favourite variable defined globally but that might also be a source of the error
Issue
In the case of backend errors the API is returning a valid response that is missing a profileId property.
router.post('/profileEdit', async (req, res) => {
const { id } = req.body;
const response = await Profile.findOne({ person: id });
if (response) {
res.send({ success: true, profileId: response });
} else {
res.send({ success: false, err: 'Something went wrong' }); // <-- here, no profileId
}
});
This doesn't cause axios to return a Promise rejection and the frontend code assumes the response object has certain properties.
The error object returned is { success: false, err: 'Something went wrong' } but the code is attempting to access into an undefined profileId property.
axios
.post("/users/profileEdit", { id })
.then(({ data }) => {
setPlace(data.profileId.place); // <-- here, data.profileId undefined
setAge(data.profileId.age);
setFavorite(data.profileId.favorite);
setCaption(data.profileId.cation);
profileInit(data.profileId);
});
data.profileId is undefined, and alone isn't an issue, it's later when trying to access the place property of an undefined object that an error is thrown.
Solution
You can keep the backend code and do a check in the frontend for a successful POST request.
axios
.post("/users/profileEdit", { id })
.then(({ data }) => {
if (data.success) {
// POST success
setPlace(data.profileId.place);
setAge(data.profileId.age);
setFavorite(data.profileId.favorite);
setCaption(data.profileId.cation);
profileInit(data.profileId);
} else {
// POST failure, check error
// access data.err
}
});
It would be better to return a non-200 status code so axios can throw/handle a rejected Promise. You can read more about HTTP status codes here. Below I'm returning a super general Status 500 error, but you will want to be a specific as you need to be, i.e. a 404 if the specific person object isn't found.
Example:
router.post('/profileEdit', async (req, res) => {
const { id } = req.body;
const response = await Profile.findOne({ person: id });
if (response) {
res.send({ profileId: response });
} else {
res.status(500).send({ err: 'Something went wrong' });
}
});
...
axios
.post("/users/profileEdit", { id })
.then(({ data }) => {
// 200 responses
const {
profileId,
profileId: { age, cation, favorite, place },
} = data;
setPlace(place);
setAge(age);
setFavorite(favorite);
setCaption(cation);
profileInit(profileId);
})
.catch(error => {
// non-200 responses
});
Trying to pass in an _id to allow my comments to post to my front end React app. When I test express route in postman I don't get the comment . See screen shot below. When I try to post the comment I get the reference error _id id not defined.
Update:
The _id is fixed with id: data._id but I am not able to see my comments when I test in browser:
Here is backend express/node GalleryController.js
const mongoose = require('mongoose');
const Posts = mongoose.model('posts');
exports.PostGalleryInput = async (req, res) => {
console.log(req.body);
await new Posts({
body: req.body,
_id: req.params.id
}).save(async (err, data) => {
if (err) {
console.log('err:', err);
res.status(500).json({
message: 'Something went wrong, please try again later.'
});
} else {
res.status(200).json({
message: 'Post Created',
data,
id: _id
});
}
});
};
Here is Data Schema:
const mongoose = require('mongoose');
const PostSchema = new mongoose.Schema(
{
id: String,
title: String,
body: String,
name: String,
url: String,
comment: String
},
{
collection: 'posts'
}
);
module.exports = mongoose.model('posts', PostSchema);
Here is front end React component
import React, { useState, useEffect } from 'react';
import Container from 'react-bootstrap/Container';
import Card from 'react-bootstrap/Card';
import Button from 'react-bootstrap/Button';
import axios from 'axios';
import './css/sharewall.css';
const Cards = () => {
const [posts, setPosts] = useState([]);
const [comment, setComment] = useState('');
const loadPosts = async () => {
try {
let res = await axios.get(`http://localhost:5000/getall`);
setPosts(res.data.reverse());
} catch (error) {
console.log(error);
}
};
function saveComment(e, _id) {
e.preventDefault();
axios({
method: 'POST',
url: 'http://localhost:5000/postinput',
data: {
_id: _id,
comment: comment
}
})
.then((res) => {
loadPosts();
})
.catch((err) => {
console.log(err);
});
}
const loadComment = async () => {
try {
let res = await axios.post('http://localhost:5000/postinput');
setComment(res.data.comment._id);
console.log(res.data.comment._id);
} catch (error) {
console.log(error);
}
};
useEffect(() => {
loadPosts();
loadComment();
}, []);
return (
<div className="compoentclass">
<Container className="mt-5 ml-auto mr-auto">
<div className="text-center">
{posts.map(
(post) =>
post.url && (
<div key={post._id}>
<Card className="">
<Card.Img alt="" src={post.url} />
<Card.ImgOverlay className="overlay">
<Card.Title className="d-flex justify-content-center align-items-center">
<Card.Text className="cardStyle text-light">{post.body}</Card.Text>
</Card.Title>
</Card.ImgOverlay>
</Card>
<div>
<Card.Text>{post.comment}</Card.Text>
</div>
<textarea
className="comment text-center mt-3 mb-3"
onChange={(e) => setComment(e.target.value)}
name="comment"
type="text"
/>
<div className="d-flex justify-content-start mt-n3 mb-4">
<Button
className="shareButton"
variant="secondary"
onClick={(e) => saveComment(e, post._id)}
>
Comment
</Button>
</div>
</div>
)
)}
</div>
</Container>
</div>
);
};
export default Cards;
I am building an app, sort of dictionary app. In my app a user can add, update and delete a word. Something happened and now my update function does not work. I don't understand why. When I click an update button an error appears in the console. Your hints and suggestions are appreciated.
Word update API
// #route Put api/words/:id
// #desc Update a word by id
// #access Private
router.put(
'/:id',
passport.authenticate('jwt', { session: false }),
(req, res) => {
const { errors, isValid } = validateWordInput(req.body);
// Check validation
if (!isValid) {
// Return any errors
return res.status(400).json(errors);
}
Profile.findOne({ user: req.user.id }).then(profile => {
Word.findById(req.params.id).then(word => {
// Check for word owner
if (word.user.toString() !== req.user.id) {
return res.status(401).json({ notauthorized: 'User not authorized' });
}
const wordID = req.params.id;
const wordInput = req.body;
// Update
Word.findByIdAndUpdate(
{ _id: wordID },
{ $set: wordInput },
{ returnOriginal: false },
(err, word) => {
if (err) {
console.log(err);
}
}
)
.then(word => {
res.json(word);
})
.catch(err =>
res
.status(404)
.json({ wordcannotbeupdated: 'word cannot be updated' })
);
});
});
}
);
Word actions
export const updateWord = (id, updatedWord, history) => dispatch => {
axios
.put(`/api/words/${id}`, updatedWord)
.then(res => {
dispatch({
type: UPDATE_WORD,
payload: res.data
});
history.push('/my-words');
})
.catch(err =>
dispatch({
type: UPDATE_WORD,
payload: ''
})
);
};
Word reducer
import {
GET_WORDS_BY_USER,
ADD_WORD,
UPDATE_WORD,
GET_WORD_BY_ID,
DELETE_WORD,
SEARCH_WORD
} from '../actions/types';
const initialState = {
words: [],
word: {},
loading: false
};
export default function(state = initialState, action) {
switch (action.type) {
case ADD_WORD:
return {
...state,
words: [action.payload, ...state.words]
};
case GET_WORDS_BY_USER:
return {
...state,
words: action.payload
};
case GET_WORD_BY_ID:
return {
...state,
word: action.payload
};
case UPDATE_WORD:
return {
...state,
words: action.payload
};
case SEARCH_WORD:
return {
...state,
words: action.payload
};
case DELETE_WORD:
return {
...state,
words: state.words.filter(word => word._id !== action.payload)
};
default:
return state;
}
}
Edit Word React component
import React, { Component } from 'react';
import { Link, withRouter } from 'react-router-dom';
import TextFieldGroup from '../common/TextFieldGroup';
import SelectListGroup from '../common/SelectListGroup';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { getWordByID, updateWord } from '../../actions/wordActions';
import isEmpty from '../../validation/is-empty';
import {
lexisOptions,
grammarOptions,
partOfSpeechOptions,
styleOptions,
originOptions,
sphereOptions
} from './options';
class EditWord extends Component {
constructor(props) {
super(props);
this.state = {
ugrWordCyr: '',
rusTranslation: '',
example: '',
exampleTranslation: '',
origin: '',
sphere: '',
see: '',
lexis: '',
grammar: '',
partOfSpeech: '',
style: '',
errors: {}
};
this.onChange = this.onChange.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.onCheck = this.onCheck.bind(this);
}
componentWillReceiveProps(nextProps) {
if (nextProps.errors) {
this.setState({ errors: nextProps.errors });
}
if (nextProps.words.word[0]) {
nextProps.words.word.map(word => {
word.ugrWordCyr = !isEmpty(word.ugrWordCyr) ? word.ugrWordCyr : '';
word.rusTranslation = !isEmpty(word.rusTranslation)
? word.rusTranslation
: '';
word.rusTranslation = !isEmpty(word.rusTranslation)
? word.rusTranslation
: '';
word.example = !isEmpty(word.example) ? word.example : '';
word.exampleTranslation = !isEmpty(word.exampleTranslation)
? word.exampleTranslation
: '';
word.origin = !isEmpty(word.origin) ? word.origin : '';
word.sphere = !isEmpty(word.sphere) ? word.sphere : '';
word.see = !isEmpty(word.see) ? word.see : {};
word.lexis = !isEmpty(word.lexis) ? word.lexis : {};
word.grammar = !isEmpty(word.grammar) ? word.grammar : {};
word.see = !isEmpty(word.see) ? word.see : {};
word.style = !isEmpty(word.style) ? word.style : {};
this.setState({
ugrWordCyr: word.ugrWordCyr,
rusTranslation: word.rusTranslation,
example: word.example,
exampleTranslation: word.exampleTranslation,
origin: word.origin,
sphere: word.sphere,
style: word.style,
lexis: word.lexis,
grammar: word.grammar,
see: word.see,
partOfSpeech: word.partOfSpeech
});
});
}
}
componentDidMount() {
this.props.getWordByID(this.props.match.params.id);
}
onSubmit(e) {
e.preventDefault();
const wordData = {
ugrWordCyr: this.state.ugrWordCyr,
rusTranslation: this.state.rusTranslation,
example: this.state.example,
exampleTranslation: this.state.exampleTranslation,
origin: this.state.origin,
sphere: this.state.sphere,
see: this.state.see,
lexis: this.state.lexis,
grammar: this.state.grammar,
partOfSpeech: this.state.partOfSpeech,
style: this.state.style
};
let id = this.props.match.params.id;
// Change a function to update
this.props.updateWord(id, wordData, this.props.history);
}
onChange(e) {
this.setState({ [e.target.name]: e.target.value });
}
onCheck(e) {
this.setState({
current: !this.state.current
});
}
render() {
const { errors } = this.state;
return (
<div className="add-word">
<div className="container">
<div className="row">
<div className="col-md-8 m-auto">
<Link to="/my-words" className="btn btn-light">
Go Back
</Link>
<h1 className="display-4 text-center">Edit Word</h1>
<form onSubmit={this.onSubmit}>
<TextFieldGroup
placeholder="Бала"
info="Введите слово на уйгурском"
name="ugrWordCyr"
value={this.state.ugrWordCyr}
onChange={this.onChange}
error={errors.ugrWordCyr}
/>
<TextFieldGroup
placeholder="Ребенок"
info="Введите слово на русском"
name="rusTranslation"
value={this.state.rusTranslation}
onChange={this.onChange}
error={errors.rusTranslation}
/>
<div className="form-check mb-form">
<input
type="checkbox"
className="form-check-input"
name="see"
value={this.state.see}
onChange={this.onCheck}
id="see"
/>
<label htmlFor="see">Смотри</label>
</div>
<TextFieldGroup
placeholder=""
info="Введите пример предложения на уйгурском"
name="example"
value={this.state.example}
onChange={this.onChange}
error={errors.example}
/>
<TextFieldGroup
placeholder=""
info="Введите перевод примерного предложения на русском"
name="exampleTranslation"
value={this.state.exampleTranslation}
onChange={this.onChange}
error={errors.exampleTranslation}
/>
<h6>Происхождение слова</h6>
<SelectListGroup
placeholder="Арабское"
name="origin"
value={this.state.origin}
onChange={this.onChange}
error={errors.origin}
options={originOptions}
/>
<h6>Сфера употребления слова</h6>
<SelectListGroup
placeholder="Физика"
name="sphere"
value={this.state.sphere}
onChange={this.onChange}
error={errors.sphere}
options={sphereOptions}
/>
<h6>Лексика слова</h6>
<SelectListGroup
placeholder="лексика"
name="lexis"
value={this.state.lexis}
onChange={this.onChange}
error={errors.lexis}
options={lexisOptions}
/>
<h6>Стиль слова</h6>
<SelectListGroup
placeholder="стиль"
name="style"
value={this.state.style}
onChange={this.onChange}
error={errors.style}
options={styleOptions}
/>
<h6>Часть речи</h6>
<SelectListGroup
placeholder=""
name="partOfSpeech"
value={this.state.partOfSpeech}
onChange={this.onChange}
error={errors.partOfSpeech}
options={partOfSpeechOptions}
/>
<h6>Грамматика слова</h6>
<SelectListGroup
placeholder="грамматика"
name="grammar"
value={this.state.grammar}
onChange={this.onChange}
error={errors.grammar}
options={grammarOptions}
/>
<input
type="submit"
value="submit"
className="btn btn-info btn-block mt-4"
/>
</form>
</div>
</div>
</div>
</div>
);
}
}
EditWord.propTypes = {
getWordByID: PropTypes.func.isRequired,
errors: PropTypes.object.isRequired,
updateWord: PropTypes.func.isRequired
};
const mapStateToProps = state => ({
errors: state.errors,
words: state.words
});
export default connect(
mapStateToProps,
{ getWordByID, updateWord }
)(withRouter(EditWord));
axios
.put(/api/words/${id}, updatedWord)
if you are using relative api endpoint then it will be going to request to
<react-server-host:port(which is 3000 in your case)>/api/words/${id}
and i am assuming you are running your backend service on another port than 3000 . Thats why it is giving error 404 not found
So when you are requesting api, write absolute endpoint
<backend-server-host:port>/api/words/${id}