GET request does not have latest entry inside - reactjs

I made an Event Feed in React. Here is the structure (I've removed unrelated components:
App.js
|_EventFeed.js
|_EventCreate.js
My problem is this:
When I create an event in EventCreate, I hope for the EventFeed to update with the latest entry but it does not happen. It does update eventually after a few seconds or refreshes - and I think this delay is because I'm using free Heroku dynos on the back-end.
How can I make it update automatically?
Code here:
EventFeed.js
import React from 'react';
import {
Button,
Row,
Col,
CardBody,
CardSubtitle,
Container,
CardText,
CardTitle,
Progress,
} from 'reactstrap';
import axios from 'axios';
import Loader from '../images/loader.gif';
import { Link } from "react-router-dom";
import nightWorkout from "../images/nightWorkout.jpg";
class EventFeed extends React.Component {
constructor(props) {
super(props);
this.state = {
message: true,
eventsList: [],
isLoading: true,
eventsJoined:0
}
}
//retrieve all events via axios
componentDidMount() {
axios.get('https://final-project-healthy.herokuapp.com/api/v1/events/')
.then(response => {
let tempEventList = response.data;
this.setState({ eventsList: tempEventList, isLoading: false })
})
.catch(error => {
console.log('ERROR: ', error);
})
}
refreshFeed = () =>{
axios.get('https://final-project-healthy.herokuapp.com/api/v1/events/')
.then(response => {
let tempEventList = response.data;
this.setState({ eventsList: tempEventList, isLoading: false })
})
.catch(error => {
console.log('ERROR: ', error);
})
}
componentDidUpdate(){
this.refreshFeed();
}
handleSubmit = e =>{
//make an api call to guestlist and add or delete current user to guest list
let event_id = e.target.id
let JWT = localStorage.getItem('userToken')
axios.post('https://final-project-healthy.herokuapp.com/api/v1/guestlists/',
{event_id:event_id},
{
headers:{
Authorization: `Bearer ${JWT}`
}
}
).then(response => {
console.log(response);
this.refreshFeed();
}).catch(error => {
console.log("ERROR in request: ", error)
})
}
render() {
const { eventsList, isLoading } = this.state;
return (
<div style={{backgroundImage: `url(${nightWorkout})`, backgroundSize:'cover', backgroundAttachment:'fixed', height:'100wh'}}>
<div>
<h1 className="text-center text-light shadow">Events Near You</h1>
<h4 className="text-center text-light shadow">Don't see a fitness meet you like? How about <Link to={'/events/create'}>creating your own</Link>?</h4>
{isLoading ?
<Container>
<Row className="d-flex align-items-center justify-content-center">
<img src={Loader} alt="Loading event feed" />
</Row>
</Container>
:
eventsList.map((eventInList) => {
let guestlist=[]
if (eventInList.guests.includes(this.props.current_user.id)){
console.log('The user is here!')
}
return (
<Container key={eventInList.id} className="my-2 bg-none">
<Row md="10" className="d-flex align-items-center rounded bg-info" style={{opacity:'0.9'}}>
<Col md="4" className=" d-flex justify-content-center align-item-center rounded">
<img width="200px" height="200px" className="border border-white m-3 rounded justify-content-center" src={eventInList.image} alt="event image" />
</Col>
<Col md="8" className="rounded">
<CardBody className="p-1 text-left">
<CardTitle><h3 className='text-light'>{eventInList.name}</h3></CardTitle>
<CardSubtitle className='text-light'>{eventInList.time}</CardSubtitle>
<CardText className='text-light'>Host : {eventInList.host.username}</CardText>
<CardText className='text-light'>Location:{eventInList.location}<br/>What to expect:{eventInList.description}</CardText>
<CardText className="text-light">Capacity: {eventInList.guests.length}/{eventInList.max_number}</CardText>
<Row className="align-items-center">
<Col md="8">
<Progress color="success" value={Math.floor(eventInList.guests.length/eventInList.max_number*100)} />
</Col>
<Col md="4">
{eventInList.guests.includes(this.props.current_user.id)
?
<Button id={eventInList.id} color="danger" onClick={this.handleSubmit}>Leave</Button>
:
<Button id={eventInList.id} color="success" onClick={this.handleSubmit}>Join</Button>
}
</Col>
</Row>
</CardBody>
</Col>
</Row>
</Container>)
})
}
</div>
</div>
)
}
}
export default EventFeed;
EventCreate.js
import React from 'react';
import {
Card,
CardImg,
CardText,
Button,
Col,
Form,
FormText,
FormGroup,
Input,
Label,
Row,
} from "reactstrap"
import axios from 'axios';
import PlacesWithStandaloneSearchBox from "../components/PlacesWithStandaloneSearchBox";
import { Link } from "react-router-dom";
import Loader from "../images/loader.gif";
import morningRun from "../images/morning_run.jpg"
class EventCreate extends React.Component {
constructor(props) {
super(props);
this.imageUpload=React.createRef();
this.state = {
eventName: '',
description: '',
location: '',
time: '',
maxNumber: '',
isLoading:false,
previewImage:null,
imageFile:null,
message:''
}
}
handleChange = e => {
this.setState({ [e.target.id]: e.target.value }, () => {
//for debugging purposes, this ensures that the state is updated with the field values
for (const key in this.state) {
if (this.state.hasOwnProperty(key)) {
console.log(key + " -> " + this.state[key] + ` of data type ${typeof (this.state[key])}`);
}
}
})
console.clear()
}
liftMyLocationUp = locationFromGoogle => {
this.setState({ location: locationFromGoogle })
}
//handleSubmit lifts up field values
handleSubmit = (e) => {
let formData = new FormData()
formData.append("image_file", this.state.imageFile, this.state.imageFile.name);
formData.append("name", this.state.eventName);
formData.append("description", this.state.description);
formData.append("max_number", this.state.maxNumber);
formData.append("time", this.state.time);
formData.append("location", this.state.location);
console.log('handleSubmit called')
this.registerEvent(formData);
setTimeout(() => this.props.history.push('/events'), 2000);
}
handleFile = (e) =>{
console.log(e.target.files[0])
this.setState({
imageFile:e.target.files[0],
previewImage:URL.createObjectURL(e.target.files[0]),
})
}
//necessary to setState? why not just keep it as props or make ?
registerEvent = (formData) => {
let JWT = localStorage.getItem('userToken')
axios.post('https://final-project-healthy.herokuapp.com/api/v1/events/',
formData,
{
headers: {
'Authorization': `Bearer ${JWT}`
}
}
).then(response => {
if (response.data.success){
console.log(response.data.success)
}
}).catch(error => {
console.log("ERROR in request: ", error);
})
}
handleClick = () =>{
this.imageUpload.current.click();
}
render() {
const { event_name, description, location, max_number, time, isLoading, previewImage, imageFile, message } = this.state
return (
<div style={{backgroundImage: `url(${morningRun})`, backgroundSize:'cover', height:'100vh'}}>
<h3 className="text-center text-light">Create Your Event Here:</h3>
<Row className="d-flex justify-content-center">
<Col lg="4" md="5" sm="12" className="d-flex justify-content-center">
<Form className="d-flex justify-content-center">
<FormGroup >
<Label for="eventName" className="text-light">Event Name:</Label>
<Input id="eventName" type="text" value={event_name} onChange={this.handleChange} placeholder="Give me a name"></Input>
<Label for="description" className="text-light">Description:</Label>
<Input id="description" type="text" value={description} onChange={this.handleChange} placeholder="Share what I'm about"></Input>
<Label for="location" className="text-light">Location:</Label>
<PlacesWithStandaloneSearchBox liftMyLocationUp={this.liftMyLocationUp} />
{/* <Input id="location" type="text" value={location} onChange={this.handleChange} placeholder="Tell folks where to find me"></Input> */}
<Label for="time" className="text-light">Time:</Label>
<Input id="time" type="datetime-local" value={time} onChange={this.handleChange}></Input>
<Label for="maxNumber" className="text-light">Max Number:</Label>
<Input id="maxNumber" type="number" min="0" value={max_number} onChange={this.handleChange} placeholder="It's always better with company"></Input>
<div> </div>
</FormGroup>
</Form>
</Col>
<Col lg="4" md="5" sm="12" className="d-flex justify-content-center">
<Row>
<Form>
<FormGroup>
<Label className="d-block text-light">Upload your event image here:</Label>
<div id="image-preview" onClick={this.handleClick}>
<Card style={{width:"300px", height:"300px"}} className="d-flex justify-content-center align-items-center">
{/* Set loading icon when uploading picture. nested ternary operator. */}
{!isLoading?(!imageFile?(<h4 className="text-center">{message ? message : "Click to upload"}</h4>):(<CardImg src={previewImage} height="300px" width="300px"/>)):<Loader/>}
</Card>
</div>
<input id="upload" style={{display:"none"}} type="file" accept="image/*" multiple={false} name="image-file" ref={this.imageUpload} id="imageFile" onChange={this.handleFile}></input>
</FormGroup>
<FormGroup>
<div id="image-submit-form">
<Row >
<Col md={12} sm={12}>
</Col>
</Row>
</div>
</FormGroup>
</Form>
</Row>
</Col>
</Row>
<Row>
<Col className="d-flex justify-content-center">
<Button color="primary" className="text-light" onClick={this.handleSubmit}>Create Event</Button>
</Col>
</Row>
</div>
)
}
}
export default EventCreate;

Related

React react-bootstrap TypeError: this.state is null

The project is a Django React project. I want to add and edit employees. To display the employees is working fine. I tried already several different solution which I found in the www but I can not solve the issue.
I do not understand why the warning occurres on the console: Warning: Each child in a list should have a unique "key" prop.
I have a key={} in the tag. Does the AddEmployee.jsx or EditEmployee.jsx file do not have access to the DepartmentId and DepartmentName? How can I check this if the files has just no access to these?
What I have tried, I can not really remember... I changed the Form.Controle to Form.Select in EditEmployee.jsx. In AddEmployee.jsx I have not changed the code so you can see the previous version.
Employee.jsx:
import React from 'react';
import { Table } from 'react-bootstrap';
import { Button, ButtonToolbar } from 'react-bootstrap';
import AddEmployee from './AddEmployee';
import EditEmployee from './EditEmployee';
export default class Employee extends React.Component {
constructor(props) {
super(props);
this.state={employees:[], addEmployee:false, editEmployee:false};
}
refreshList() {
fetch(process.env.REACT_APP_API+'employee/')
.then(response => response.json())
.then(data => {
this.setState({employees:data});
});
}
componentDidMount() {
this.refreshList();
}
componentDidUpdate() {
this.refreshList();
}
deleteEmployee(employeeid) {
if(window.confirm('Are you sure?')) {
fetch(process.env.REACT_APP_API+'employee/'+employeeid, {
method:'DELETE',
header:{'Accept': 'application/json', 'Content-Type': 'application/json'}
})
}
}
render() {
const { employees, employeeid, employeename, department, photo, datejoining } = this.state;
let addEmployeeClose = () => this.setState({addEmployee:false});
let editEmployeeClose = () => this.setState({editEmployee:false});
return (
<div>
<Table
className="mt-4"
striped bordered hover size="sm">
<thead>
<tr>
<th>Employee Id</th>
<th>Employee Name</th>
<th>Department</th>
<th>Joining Date</th>
<th>Options</th>
</tr>
</thead>
<tbody>
{employees.map(emp =>
<tr key = {emp.EmployeeId}>
<td>{emp.EmployeeId}</td>
<td>{emp.EmployeeName}</td>
<td>{emp.Department}</td>
<td>{emp.DateOfJoining}</td>
<td>
<ButtonToolbar>
<Button
className="mr-2"
variant="info"
onClick={() => this.setState(
{editEmployee:true,
employeeid:emp.EmployeeId,
employeename:emp.EmployeeName,
department:emp.Department,
photo:emp.PhotoFileName,
datejoining:emp.DateOfJoining})}>
Edit
</Button>
<Button
className="mr-2"
variant="danger"
onClick={() => this.deleteEmployee(emp.EmployeeId)}>
Delete
</Button>
<EditEmployee
show={this.state.editEmployee}
onHide={editEmployeeClose}
employeeid={employeeid}
employeename={employeename}
department={department}
photo={photo}
datejoining={datejoining} />
</ButtonToolbar>
</td>
</tr>)}
</tbody>
</Table>
<ButtonToolbar>
<Button
variant="primary"
onClick= {() => this.setState({addEmployee:true})}>
Add Employee
</Button>
<AddEmployee
show={this.state.addEmployee}
onHide={addEmployeeClose} />
</ButtonToolbar>
</div>
)
}
}
EditEmplyee.jsx:
import React from 'react';
import { Modal, Button, Row, Col, Form, Image } from 'react-bootstrap';
export default class EditEmployee extends React.Component {
constructor(props) {
super(props);
this.handleSubmit=this.handleSubmit.bind(this);
}
handleSubmit(event) {
event.preventDefault();
fetch(process.env.REACT_APP_API+'employee', {
method:'PUT',
headers: {
'Accept': 'applications/json',
'Content-Type': 'application/json'
},
body:JSON.stringify({
EmployeeId:event.target.EmployeeID.value,
EmployeeName:event.target.EmployeeName.value,
Department:event.target.Department.value,
DateOfJoining:event.target.DateOfJoining.value,
PhotoFileName:this.photo
})
})
.then(res => res.json())
.then(result => {
alert(result);
},
(error) => {
alert('Failed');
})
}
render() {
return (
<div className="container">
<Modal
{...this.props}
size="lg"
aria-labelledby="contained-modal-title-vecenter"
centered
>
<Modal.Header cloosebutton="true">
<Modal.Title
id="contained-modal-title-vecenter">
Edit Employee
</Modal.Title>
</Modal.Header>
<Modal.Body>
<Row>
<Col sm={6}>
<Form onSubmit={this.handleSubmit}>
<Form.Group controlId="EmployeeId">
<Form.Label>Employee Id</Form.Label>
<Form.Control
type="text"
name="EmployeeId"
required
disabled
defaultValue = {this.props.employeeid}
placeholder="Employee Id"/>
</Form.Group>
<Form.Group controlId="EmployeeName">
<Form.Label>Employee Name</Form.Label>
<Form.Control
type="text"
name="EmployeeName"
required
defaultValue = {this.props.employeename}
placeholder="Employee Name"/>
</Form.Group>
<Form.Group controlId="Department">
<Form.Label>Department</Form.Label>
<Form.Select
defaultValue = {this.props.department}
>
{this.state.departments.map(dep => (
<option
key={dep.DepartmentId}
value={dep.DepartmentName}
/>
))
}
</Form.Select>
</Form.Group>
<Form.Group controlId="DateOfJoining">
<Form.Label>Joined Date</Form.Label>
<Form.Control
type="date"
name="DateOfJoining"
required
defaultValue = {this.props.datejoining}
placeholder="Joining Date"
/>
</Form.Group>
<Form.Group>
<Button
variant="primary"
type="submit">
Update Employee
</Button>
</Form.Group>
</Form>
</Col>
<Col sm={6}>
<Image
width="200px"
height="200px"
src={process.env.REACT_APP_PHOTOPATH+this.props.photo}
/>
<input onChange={this.handleFileSelected} type="File" />
</Col>
</Row>
</Modal.Body>
<Modal.Footer>
<Button
variant="danger"
onClick={this.props.onHide}>
Close
</Button>
</Modal.Footer>
</Modal>
</div>
)
}
}
AddEmplyee.jsx:
import React from 'react';
import { Modal, Button, Row, Col, Form, Image } from 'react-bootstrap';
export default class AddEmployee extends React.Component {
constructor(props) {
super(props);
this.state={departments:[]}
this.handleSubmit=this.handleSubmit.bind(this);
this.handleFileSelected=this.handleFileSelected.bind(this);
}
photo = 'book.png';
imagesrc = process.env.REACT_APP_PHOTOPATH+this.photo;
componentDidMount() {
fetch(process.env.REACT_APP_API+'employee/')
.then(response => response.json())
.then(data => {
this.setState({departments:data});
});
}
handleSubmit(event) {
event.preventDefault();
fetch(process.env.REACT_APP_API+'employee/', {
method:'POST',
headers: {
'Accept': 'applications/json',
'Content-Type': 'application/json'
},
body:JSON.stringify({
EmployeeId:null,
EmployeeName:event.target.EmployeeName.value,
Department:event.target.Department.value,
DateOfJoining:event.target.DateOfJoining.value,
PhotoFileName:this.photo
})
})
.then(res => res.json())
.then(result => {
alert(result);
},
(error) => {
alert('Failed');
})
}
handleFileSelected(event) {
event.preventDefault();
this.photo=event.target.files[0].name;
const formData = new FormData();
formData.append(
"myFile",
event.target.files[0],
event.target.files[0].name
);
fetch(process.env.REACT_APP_API+'employee/saveFile', {
method:'POST',
body:formData
})
.then(res => res.json())
.then((result) => {
this.imagesrc=process.env.REACT_APP_PHOTOPATH+result;
},
(error) => {
alert('Failed');
})
}
render() {
return (
<div className="container">
<Modal
{...this.props}
size="lg"
aria-labelledby="contained-modal-title-vecenter"
centered
>
<Modal.Header cloosebutton="true">
<Modal.Title
id="contained-modal-title-vecenter">
Add Employee
</Modal.Title>
</Modal.Header>
<Modal.Body>
<Row>
<Col sm={6}>
<Form onSubmit={this.handleSubmit}>
<Form.Group controlId="EmployeeName">
<Form.Label>Employee Name</Form.Label>
<Form.Control
type="text"
name="EmployeeName"
required
placeholder="Employee Name"/>
</Form.Group>
<Form.Group controlId="Department">
<Form.Label>Department</Form.Label>
<Form.Control as="select">
{this.state.departments.map((dep) =>
<option key={dep.DepartmentId} >
{dep.DepartmentName}
</option>
)};
</Form.Control>
</Form.Group>
<Form.Group controlId="DateOfJoining">
<Form.Label>Joined Date</Form.Label>
<Form.Control
type="date"
name="DateOfJoining"
required
placeholder="Joining Date"
/>
</Form.Group>
<Form.Group>
<Button
variant="primary"
type="submit">
Add Employee
</Button>
</Form.Group>
</Form>
</Col>
<Col sm={6}>
<Image
width="200px"
height="200px"
src={this.imagesrc}
/>
<input onChange={this.handleFileSelected} type="File" />
</Col>
</Row>
</Modal.Body>
<Modal.Footer>
<Button
variant="danger"
onClick={this.props.onHide}>
Close
</Button>
</Modal.Footer>
</Modal>
</div>
)
}
}
console:

I am getting this error Minified React error #130 after creating a production build of Create-React-App

The error only shows up when I visit login page in the application, however the register page looks fine.
The form in the login page is created with reactstrap. The application works fine in development mode, as soon as I created production build using yarn build the problem arose.
Following is my Login.js Component
import React, { Component } from 'react';
import { Button, Col, Container, Row, Form, FormGroup, Input, Label, Alert } from 'reactstrap';
import axios from 'axios';
import { Link } from 'react-router-dom';
import { AuthContext } from '../contexts/AuthContext';
class Login extends Component {
static contextType = AuthContext;
state = {
isSubmitting: false,
failed: false
}
handleSubmit = e => {
e.preventDefault();
this.setState({
isSubmitting: true
});
const loginData = {
email: this.email,
password: this.password
}
axios.post('login', loginData)
.then( res => {
this.setState({
isSubmitting: false
});
if(res.status === 200){
const user = res.data.data;
const userData = {
id: user.id,
name: user.name,
api_token: user.api_token
}
if(user){
this.context.setUser(userData);
this.context.storeUser(userData);
this.context.setAuthenticated(true);
let pageToGo;
if(this.props.history.location.state !== undefined){
const pageFrom = this.props.history.location.state.page;
pageToGo = pageFrom ? pageFrom : '/dashboard';
this.props.history.push(pageToGo);
}else{
this.props.history.push('/dashboard');
}
}else{
this.setState({
failed: true
});
}
}else{
this.setState({
failed: true
});
}
} )
.catch( err => {
console.log(err);
})
}
handleLogout = () => {
this.context.logout();
this.props.history.push('/');
}
RenderErrorMessages = () => {
if(this.state.failed){
return(
<div>
<Alert color="danger">Invalid Credentials! Try again with correct credentials!</Alert>
</div>
)
}else{
return(
<div>
</div>
)
}
}
RenderDashboard = () => {
return(
<div>
<Container className="shadow-sm" style={{backgroundColor: '#fff'}}>
<Row className="p-5" color="white" >
<Col className="pb-4 border-bottom" md="12">
<h2 className="mb-3">Hi, {this.context.user.name}</h2>
<h5 className="font-weight-normal">You are logged in!</h5>
</Col>
</Row>
<Row className="pb-5 px-5">
<Col md="6">
<Col md="12">
<p>Do you want to go to your dashboard?</p>
<Button className="mr-2" tag={Link} to="/dashboard">Go to Dashboard</Button>
</Col>
<Col md="12" className="mt-4">
<p>Do you want to logout?</p>
<Button onClick={() => this.handleLogout()} >Log Out</Button>
</Col>
</Col>
</Row>
</Container>
</div>
)
}
RenderLoginForm = () => {
return (
<Container className="py-5" >
<Row className="justify-content-center">
<Col md="8">
<h3 className="pb-3 mb-2 text-uppercase font-weight-bold text-sm" style={{fontSize: '18px'}}>Login to start your session!</h3>
</Col>
</Row>
<Row className="justify-content-center">
<Col md="8">
<this.RenderErrorMessages />
</Col>
</Row>
<Row className="justify-content-center">
<Col className="p-5 shadow-sm" md="8" style={{backgroundColor: '#fff'}}>
<Form onSubmit={this.handleSubmit}>
<FormGroup>
<Label htmlFor="email" className="font-weight-bold">Email</Label>
<Input
type="email"
name="email"
placeholder="Enter Your Email"
onChange={e => this.email = e.target.value}
required={true}
/>
</FormGroup>
<FormGroup>
<Label htmlFor="password" className="font-weight-bold">Password</Label>
<Input
type="password"
name="password"
placeholder="Enter Your Password"
onChange={e => this.password = e.target.value}
required={true}
/>
</FormGroup>
<Button className="mt-4" type="submit" name="submit" disabled={this.state.isSubmitting}>{this.state.isSubmitting ? 'loading..' : 'Submit'}</Button>
<p className="text-right mt-2">Don't have an account? <Link to="/register">Sign Up Here</Link></p>
</Form>
</Col>
</Row>
</Container>
)
}
render() {
return(
<div className="py-5" style={{backgroundColor: '#f5f5f5'}}>
{this.context.authenticated ? <this.RenderDashboard /> : <this.RenderLoginForm />}
</div>
)
}
}
export default Login;
Here is the complete log of the error.
Error: Minified React error #130; visit https://reactjs.org/docs/error-decoder.html?invariant=130&args[]=undefined&args[]= for the full message or use the non-minified dev environment for full errors and additional helpful warnings.

axios post method just not responding with anything

i have this axios post method in my Action creator in my reactJS app but for some reason, I don't understand why, the post method is frozen and doesn't do anything. I have a similar implementation in my one of the other project that's working fine but this isn't. The console.log() shows nothing, no error no response. Please help, thanks in advance.
export const addNewPost = (data) =>(dispatch) => {
dispatch(newPostLoading);
console.log("addNewPost triggered");
return (dispatch) => {
axios
.post("/posts.json", data)
.then((response) => {
console.log(response.data);
dispatch(newPostSuc());
})
.catch((err) => {
console.log(err);
dispatch(newPostFailed(err));
});
};
};
This is what my caller component looks like :
import React, { Component } from "react";
import { connect } from "react-redux";
import { Redirect } from "react-router-dom";
import { Button, Row, Col, Label } from 'reactstrap';
import { Control, LocalForm } from 'react-redux-form';
import { addNewPost } from '../redux/ActionCreators';
import {Loading} from './LoadingComponent';
class NewPost extends Component {
addPostHandler = (event) => {
const data ={
title: event.title,
author: event.author,
content: event.content,
image:''
}
this.props.addNewPost(data);
};
render() {
if(this.props.newPost.isLoading)
{
return (<Loading/>);
}
let redirectElement = null;
if (this.props.newPost.redirect) {
redirectElement = <Redirect to="/" />;
}
return (
<>
{redirectElement}
<div className="container">
<LocalForm onSubmit={(values) => this.addPostHandler(values) }>
<Row className="form-group">
<Label htmlFor="title" md={2}><strong>Post Title</strong></Label>
<Col md={10}>
<Control.text model=".title" id="title" name="title"
placeholder="Catchy title here bitch"
className="form-control"
/>
</Col>
</Row>
<Row className="form-group">
<Label htmlFor="author" md={2}><strong>Author</strong></Label>
<Col md={10}>
<Control.text model=".author" id="author" name="author"
placeholder="Author"
className="form-control"
/>
</Col>
</Row>
<Row className="form-group">
<Label htmlFor="content" md={2}><strong>Post Description</strong></Label>
<Col md={10}>
<Control.textarea model=".content" id="content" name="content"
rows="12" placeholder="You saw shit? Time to step on it"
className="form-control" />
</Col>
</Row>
<Row className="form-group">
<Col md={{size:10, offset: 2}}>
<Button type="submit" color="primary">
Send Post
</Button>
</Col>
</Row>
</LocalForm>
</div>
</>
);
}
}
const mapStateToProps = (state) => {
return {
newPost: state.newPost
};
};
const mapDispatchToProps = (dispatch) => {
return {
addNewPost: (data) => {dispatch(addNewPost(data))}
};
};
export default connect(mapStateToProps, mapDispatchToProps)(NewPost);

react is editing all array objects instead of just one array object

Currently a user can enter first, lastname, and employee id. When it submits it renders an iteration of employees with the first, last, and employee id.
The problem is when you click edit, it edits the data but it will edit all of the fields for every object in the employees iteration.
How can I fix the code so that it will edit just that particular object within that iteration.
Home component
........
class Login extends Component {
constructor(props) {
super(props);
this.state = {
activeTab: '3',
firstName: '',
lastName: '',
employeeID: '',
employees: [],
Edit: false,
updatedFirst: '',
updatedLast:'',
updatedEmployeeID: ''
};
}
toggle = (tab) => {
if(this.state.activeTab !== tab){
this.setState({
activeTab: tab
})
}
}
onSubmit = (e) => {
e.preventDefault();
const {firstName, lastName, employeeID} = this.state
const ourForm ={
firstName: firstName,
lastName: lastName,
employeeID: employeeID,
// we need an id to so that it can be edited properly
}
this.setState({
employees: [...this.state.employees,ourForm]
}, () => {
console.log(this.state.employees)
})
}
onChange = (e) => {
e.preventDefault()
// e.preventDefault();
this.setState({
[e.target.name]: e.target.value,
});
}
updatedChange = (e) => {
e.preventDefault()
// e.preventDefault();
this.setState({
[e.target.name]: e.target.value,
});
}
onEdit = (e) => {
e.preventDefault();
this.setState({
Edit: !this.state.Edit
})
}
onReset = (e) => {
e.preventDefault();
this.setState({
firstName: '',
lastName: '',
employeeID: ''
})
}
render(){
return (
......
<MyForm
onSubmit={this.onSubmit}
onChange={this.onChange}
onReset={this.onReset}
firstName={this.state.firstName}
lastName={this.state.lastName}
employeeID={this.state.employeeID}
/>
</Col>
</Row>
</TabPane>
</TabContent>
</Container>
<List
employees={this.state.employees}
Edit={this.state.Edit}
onEdit ={this.onEdit}
onChange={this.onChange}
updatedEmployeeID={this.state.updatedEmployeeID}
updatedFirst={this.state.updatedFirst}
updatedLast={this.state.updatedLast}
/>
</div>
);
}
}
export default Login;
Form.js
import React, {Component} from 'react';
import { Col, Form, FormGroup, Label, Input, Button } from 'reactstrap';
const MyForm = (props) => {
return(
<Form style={{ margin: '30px 0px'}}>
<FormGroup row>
<Label for="firstName" sm={2} size="sm">First Name:</Label>
<Col sm={10}>
<Input type="text" onChange={props.onChange} value={props.firstName} name="firstName" id="exampleEmail" placeholder="Enter First Name"/>
</Col>
</FormGroup>
<FormGroup row>
<Label for="lastName" sm={2} size="sm">Last Name:</Label>
<Col sm={10}>
<Input type="text" onChange={props.onChange} value={props.lastName} name="lastName" id="exampleEmail2" placeholder="Enter Last Name" />
</Col>
</FormGroup>
<FormGroup row>
<Label for="Employee ID" sm={2} size="sm">Employee ID:</Label>
<Col sm={5}>
<Input type="text" onChange={props.onChange} value={props.employeeID} name="employeeID" id="exampleEmail2" placeholder="Enter Employee ID" />
</Col>
</FormGroup>
<FormGroup row>
<Col sm={12}>
<div className="float-right">
<Button onClick={props.onSubmit} size="lg" style={{ margin: '0px 5px'}} color="secondary">Add</Button>
<Button onClick={props.onReset} size="lg" style={{ margin: '0px 5px'}}color="warning">Reset</Button>
</div>
</Col>
</FormGroup>
<hr></hr>
<FormGroup row>
<Col sm={4}>
<Input type="text" name="search" id="exampleEmail2" placeholder="Search" />
</Col>
<Col sm={8}>
<Label for="sort" sm={2} size="sm">Sort:</Label>
<Button onClick={props.onSubmit} size="lg" style={{ margin: '0px 5px'}} color="secondary">First Name</Button>
<Button onClick={props.onSubmit} size="lg" style={{ margin: '0px 5px'}} color="secondary">Last Name</Button>
<Button onClick={props.onSubmit} size="lg" style={{ margin: '0px 5px'}} color="secondary">ID</Button>
</Col>
</FormGroup>
</Form>
)
}
export default MyForm;
List component
import React, {Component, Fragment} from 'react';
import { Col, Form, FormGroup, Label, Input, Button } from 'reactstrap';
const List = (props) => {
return(
<Fragment>
{props.employees.map( (item, i) => (
<div style={{ margin: '40px 0px'}} key={i}>
<hr style={{ border:'1px dashed #000'}}></hr>
<div className="float-right">
<Button onClick={props.onEdit} size="lg" style={{ margin: '0px 5px'}} color="secondary">{props.Edit ? 'Save': 'Edit'}</Button>
<Button size="lg" style={{ margin: '0px 5px'}}color="secondary">Delete</Button>
</div>
<FormGroup row>
<Col sm={5}>
{props.Edit ? (
<Input type="text" onChange={props.onChange} value={ props.updatedFirst ? props.updatedFirst : item.firstName } name="updatedFirst" placeholder="Enter First Name"/>
):(
<div>
{props.updatedFirst ? props.updatedFirst : item.firstName }
</div>
)}
</Col>
</FormGroup>
<FormGroup row>
<Col sm={5}>
{props.Edit ? (
<Input type="text" onChange={props.onChange} value={ props.updatedEmployeeID ? props.updatedEmployeeID : item.employeeID} name="updatedEmployeeID" placeholder="Enter EmployeeID"/>
):(
<div>
{props.updatedEmployeeID ? props.updatedEmployeeID : item.employeeID}
</div>
)}
</Col>
</FormGroup>
<FormGroup row>
<Col sm={5}>
{props.Edit ? (
<Input type="text" onChange={props.onChange} value={ props.updatedLast ? props.updatedLast: item.lastName} name="updatedLast" placeholder="Enter Last Name"/>
):(
<div>
{props.updatedLast ? props.updatedLast : item.lastName}
</div>
)}
</Col>
</FormGroup>
</div>
))}
</Fragment>
)
}
export default List;
The following example shows how to pass a handler and set the state accordingly.
For good measure I separated the logic and the presentation, the presentational components are pure components using React.memo.
//A container should only contain the logic
class EmployeesContainer extends React.Component {
state = {
employees: [{ name: '' }, { name: '' }, { name: '' }],
};
//define what needs to happen if you click edit on an
// employee
onEdit = index => {
//edit will be called with the index of the employee
// the Employees component owns the list of employees
// so it will have to make changes to it
this.setState({
employees: this.state.employees.map((employee, i) =>
i === index ? { ...employee, edit: true } : employee
),
});
};
//Same idea as onEdit, index needs to be passed to indicate
// what employee needs to be changed
onChange = (index, e) => {
this.setState({
employees: this.state.employees.map((employee, i) =>
i === index
? { ...employee, name: e.target.value }
: employee
),
});
};
render() {
return (
<Employees
employees={this.state.employees}
onEdit={this.onEdit}
onChange={this.onChange}
/>
);
}
}
//The Employees presentational component, contains the jsx
// you can make it a pure component by using React.memo
const Employees = React.memo(
({ employees, onEdit, onChange }) => (
<div>
{employees.map((employee, index) => (
<EmployeeContainer
key={index}
index={index}
employee={employee}
onEdit={onEdit}
onChange={onChange}
/>
))}
</div>
)
);
//Make this a container as well because it does more
// than only produce jsx
class EmployeeContainer extends React.Component {
state = {};
//create onChange and onEdit only when index changes
// this will prevent unnecessary renders
static getDerivedStateFromProps(props, state) {
const { index, onChange, onEdit } = props;
if (state.index !== index) {
return {
index,
onChange: e => onChange(index, e),
onEdit: () => onEdit(index),
};
}
return null;
}
render() {
const { employee } = this.props;
const { onChange, onEdit } = this.state;
return (
<Employee
employee={employee}
onChange={onChange}
onEdit={onEdit}
/>
);
}
}
//presentational component, is also pure component
const Employee = React.memo(
({ employee, onChange, onEdit }) => (
<div>
{employee.edit ? (
<input
type="text"
value={employee.name}
onChange={onChange}
/>
) : (
<button onClick={onEdit}>edit</button>
)}
</div>
)
);
I don’t think onSubmit is updating employees correctly. You shouldn’t use this.state inside setState.
this.state inside setState ReactJS
Try this..
this.setState(prevState => ({
employees: [...prevState.employees, ourForm]
}, () => {
console.log(this.state.employees)
}))

TypeError: Cannot convert undefined or null to object React Validation

I have used React validation library
https://www.npmjs.com/package/react-validation
If I visit my page from any other page, it does not give any error. but when I refresh the page, it gives an error
TypeError: Cannot convert undefined or null to object
Please suggest an idea if anybody has faced this issue before.
Code:
import React from 'react';
import {
Card,
CardBody,
CardTitle,
Row,
Col,
FormGroup,
Label,
Alert
} from 'reactstrap';
import Input from 'react-validation/build/input';
import Button from 'react-validation/build/button';
import Form from 'react-validation/build/form';
import axios from 'axios';
import api from '../../config/api';
import messages from '../../config/messages';
import Select from 'react-validation/build/select';
import CKEditor from '#ckeditor/ckeditor5-react';
import ClassicEditor from '#ckeditor/ckeditor5-build-classic';
const required = (value, props,components) => {
if(components.formReset!=undefined)
{
if (!components.formReset[0].value && (!value || (props.isCheckable && !props.checked))) {
return <span className="text-danger is-visible">{messages.required}</span>;
}
else if(components.formReset[0].value)
{
return <span className="text-danger is-visible"></span>;
}
}
}
;
class View extends React.Component {
constructor(props) {
super(props);
this.onInputChange = this.onInputChange.bind(this);
this.sendReply = this.sendReply.bind(this);
this.toggle = this.toggle.bind(this);
this.onStatusChange=this.onStatusChange.bind(this);
this.handleEditorChange=this.handleEditorChange.bind(this);
this.state = {
response:null,
loading: false,
message:'',
status:'',
attachment1:[],
status_list:[],
formReset:true
};
}
componentDidMount() {
this.setState({formReset:true});
}
onStatusChange(event) {
this.setState({"formReset":false});
this.setState({
status: event.target.value
});
}
handleEditorChange(data) {
this.setState({"formReset":false});
this.setState({ message:data });
}
sendReply()
{
/*** code after form submission***/
}
toggle() {
}
onInputChange(event) {
event.preventDefault();
this.setState({"formReset":false});
this.setState({
[event.target.name]: event.target.value
});
}
render() {
var _this = this;
return (
<aside className="customizer">
{/*--------------------------------------------------------------------------------*/}
{/* Toggle Customizer From Here */}
{/*--------------------------------------------------------------------------------*/}
<div className="customizer-body pt-3">
<div>
{/* --------------------------------------------------------------------------------*/}
{/* Start Inner Div*/}
{/* --------------------------------------------------------------------------------*/}
<Row>
<Col md="12">
<Card>
<CardTitle className=" border-bottom p-3 mb-0">
</CardTitle>
<CardBody>
<Form ref={c => {
this.replyform = c;
}}>
<Input type="hidden" name="formReset" id="formReset" value={this.state.formReset} />
<FormGroup>
<Row>
<Label sm="2">Reply *</Label>
<Col sm="10">
<CKEditor
editor={ ClassicEditor }
data={this.state.message}
config={ {
toolbar: [ 'heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'blockQuote' ]
} }
onChange={ ( event, editor ) => {
const data = editor.getData();
this.handleEditorChange(data);
} }
/>
</Col>
</Row>
</FormGroup>
<FormGroup>
<Row>
<Label sm="2">Status</Label>
<Col sm="10">
<Select id="status" className="custom-select form-control" name="status" onChange={this.onStatusChange} value={this.props.status_id: null}>
<option value="">Select</option>
{this.state.status_list.map((status, index) => {
return (
<option key={index} value={status.value}>{status.label}</option>
);
})}
</Select>
</Col>
</Row>
</FormGroup>
<FormGroup>
<Row>
<Label sm="2">Attachments</Label>
<Col sm="10">
<Input
type="file"
id="attachment1" name="attachment1[]"
onChange={this.onInputChange}
multiple="multiple"
/>
</Col>
</Row>
</FormGroup>
<div className="border-top pt-3 mt-3 d-flex no-block">
<Button type="button" onClick={this.sendReply} className="btn btn-dark mr-2 ml-auto">
Send Reply
</Button>
</div>
</Form>
</CardBody>
</Card>
</Col>
</Row>
{/* --------------------------------------------------------------------------------*/}
{/* End Inner Div*/}
{/* --------------------------------------------------------------------------------*/}
</div>
</div>
</aside>
);
}
}
export default View;
Error image:
Really crazy error:
import { Formik, Form, Field } from 'formik';
above required initial values on any cost if you dont want to give initial value initialize it with empty.for example
const initialValues = {
firstname: "",
lastname: ""
}
and then in <Formik tag
initialValues={initialValues}
I was facing the same error using formik
After debugging I came to know I had a typo in the initialValues object name. Make sure you are having the same object for initalValues that you have defined. In my case I had timeCapturesInitialValues object but used timeCapturesInitailValues in the Formik prop.
after upgrading react & it's packages i was facing above issue & it's resolved by Hassan Ali Shahzad answer,
code that may help some one
<Formik
enableReinitialize={true}
initialValues={{
heatmaps: '',
}}
if your return statement is null at any given point this error occurs.
Example:
const obj = null;
return(
obj
);
Please check your code .

Resources