react - this = undefined, how to pass the prop into my function - reactjs

I have passed my user ID into my 'OrderMessages' component but in my function says undefined. When my user submits a messages using the form in the handleFormSubmit function I need the UserID and the datetime of the message. I have managed to get the date and time but when trying to console log to get the UserID I keep getting an error. I have tried this.props.... and this.state but both say undefined, can you please help. In my constructor I have tested using const UserId = props.location.state.UserID; and in debug I can see this has correctly got the UserID so im not sure how to get it into my hadleFormSubmit function.
import React from "react";
import Moment from "moment";
import { Form, Button } from "react-bootstrap";
class OrderMessages extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
isLoading: false,
checkboxes: [],
selectedId: [],
formLableSelected: "",
formSelectedSubject: "",
formSelectedSubjectId: "",
formNewSubject: "",
formChainID: "",
formMessageBody: "",
userId: '',
};
const UserId = props.location.state.UserID;
}
componentDidMount() {
this.setState({ isLoading: true });
const proxyurl = "https://cors-anywhere.herokuapp.com/";
const url =
"myURL" +
this.props.location.state.orderNumber;
fetch(proxyurl + url)
.then((res) => res.json())
.then((data) => this.setState({ data: data, isLoading: false }));
}
handleClick = (id) => {
if (this.state.selectedId !== id) {
this.setState({ selectedId: id });
} else {
this.setState({ selectedId: null });
}
};
setformSubjectID(messageSubject) {
if (messageSubject.subject === this.state.formSelectedSubject) {
this.setState({ formSelectedSubjectId: messageSubject.messageSubjectId });
}
}
handleChangeSubject = (event) => {
this.setState({ formSelectedSubject: event.target.value });
this.state.data.message_Subjects.map((ms) => this.setformSubjectID(ms));
};
handleFormSubmit(e) {
e.preventDefault();
// get current time
let submit_time = Moment().format("ddd DD MMM YYYY HH:mm:ss");
console.log("messageDatetime", submit_time);
// get user id THIS IS WHAT DOESN’T WORK
console.log("messageSentFrom", this.state.userId);
console.log("messageSentFrom", this.props.location.state.UserID);
}
render() {
const { data, isLoading } = this.state;
if (isLoading) {
return <p>Loading ...</p>;
}
if (data.length === 0) {
return <p> no data found</p>;
}
console.log("mess: ", data);
return (
<div>
<div className="sendMessageContent">
<Form className="sendMessageForm" onSubmit={this.handleFormSubmit}>
<Form.Group className="formRadio">
<Form.Check
className="formRadiob"
type="radio"
label="New chat"
value="new"
name="neworexisitng"
id="New Message"
onChange={this.onFormMessageChanged}
defaultChecked
/>
<Form.Check
className="formRadiob"
type="radio"
label="Reply to exisiting chat"
value="reply"
name="neworexisitng"
id="exisiting Message"
onChange={this.onFormMessageChanged}
/>
</Form.Group>
{this.returnCorrectFormFields(data)}
<Form.Group>
<Form.Label>Message Body</Form.Label>
<Form.Control as="textarea" rows={3} />
</Form.Group>
<Button variant="primary" type="submit">
Send Message
</Button>
</Form>
</div>
</div>
);
}
returnCorrectFormFields(data) {
if (this.state.formLableSelected === "new") {
return this.newMessageSubject(data);
} else {
return this.choseMessageSubject(data);
}
}
choseMessageSubject(data) {
return (
<Form.Group>
<Form.Label>Select the message subject</Form.Label>
<Form.Control as="select" onChange={this.handleChangeSubject}>
<option value="0">Choose...</option>
{data.message_Subjects.map((ms) => (
<option value={ms.subject}>{ms.subject}</option>
))}
</Form.Control>
</Form.Group>
);
}
newMessageSubject(data) {
return (
<Form.Group>
<Form.Label>Enter Message Subject</Form.Label>
<Form.Control type="text" placeholder="Enter message subject" />
</Form.Group>
);
}
onFormMessageChanged = (event) => {
this.setState({
formLableSelected: event.target.value,
});
};
getAllMessageInChain(messageChain) {
return (
<div className="messageHistory">
<div className="messageHistoryHeader">
<div className="innerMS-history-body">Message</div>
<div className="innerMS">Date and Time</div>
<div className="innerMS">Message sent by</div>
</div>
{messageChain.map((ms) => (
<div className="messageHistoryBody">
<div className="innerMS-history-body">{ms.messageBody}</div>
<div className="innerMS">
{Moment(ms.dateTime).format("ddd DD MMM YYYY hh:mm:ss")}
</div>
<div className="innerMS">{ms.sentFromId}</div>
</div>
))}
</div>
);
}
getLatestMessageDateTime(messageChain) {
const lastmessage = messageChain.length - 1;
Moment.locale("en");
var dt = messageChain[lastmessage].dateTime;
return Moment(dt).format("ddd DD MMM YYYY hh:mm:ss");
}
}
export default OrderMessages;

The scope of this isn't the component in the function you're using.
Either change handleFormSubmit to this to bind this automatically.
handleFormSubmit = (e) => {
// .. your code
}
or bind this manually in the constructor
constructor() {
// ..other code
this.handleFormSubmit = this.handleFormSubmit.bind(this)
}

Related

I want to clear the text fields once I click on filter button

In this code I am unable to clear both the text fields even though I'm setting their states to blank after clicking on filter via this.Search function.
import React from 'react' import Axios from './Axios' import
'./index.css' export default class Practise extends React.Component {
constructor(props) {
super(props)
this.state = {
lists: [],
names: '',
emails: '',
arr: [],
}
this.Search = (names, emails) => {
const arr = this.state.lists.filter(item => {
if (item.name.includes(this.state.names) && item.email.includes(this.state.emails)) {
return true
} else {
return false
}
})
this.setState({names:''})
this.setState({emails:''})
console.log(arr)
}
}
componentDidMount() {
Axios.get('/comments').then(response => {
// console.log(response.data, 'data')
this.setState({ lists: response.data })
}).catch(response => {
console.log(response, 'Errored!!!')
this.setState({ errored: 'Error has Occured' })
})
}
render() {
const { lists, arr, names, emails } = this.state
return (
<>
<div >
<input type='text' onChange={(e) => this.setState({ names: e.target.value })} />
<input type='text' onChange={(p) => this.setState({ emails: p.target.value })} />
<button onClick={()=>this.Search()}>Filter</button>
</div>
<div>
{lists.length ? lists.map(item =>
<div className='divone' key={item.id}>
Id:- {item.id} <br />
Name:- {item.name} <br />
Email:- {item.email}</div>) : null}
</div>
</>
)
}
};
You have to add the value prop to both of the inputs.After that,
if you change the state to a blank string, the value of inputs will also get blank.Here is an example -
<input type='text' value={this.state.names} onChange={(e) => this.setState({ names: e.target.value })} />
<input type='text' value={this.state.emails} onChange={(p) => this.setState({ emails: p.target.value })} />
It should work.

Title and event form input not posted and retrieve using Reactjs

The Reactjs code below works excellently by posting and retrieving Users newStatus from a form input to and from an API.
Now I want to add two additional form form inputs (newTitle and newEvent) as per code below
<input className="input-status" name="newTitle"
value={this.state.newTitle}
onChange={e => this.handleNewStatusChange(e)}
placeholder="your Title"
/>
<input className="input-status" name="newEvent"
value={this.state.newEvent}
onChange={e => this.handleNewStatusChange(e)}
placeholder="Your Event Centre Name"
/>
I have also implemented newEvent and newTitle variables in code where possible. My issue is that if type in the first form inputs (eg newStatus) it gets replicated or inserted in all other remaining two forms inputs as can be seen in the screenshot below.
And I believe that's why only the newStatus get posted and retrieved.
I have commented out all newEvent and newTitle variables in code so readers can see where I am wrong.
Here is the code profile.jsx:
import React, { Component } from 'react';
import {
isSignInPending,
loadUserData,
Person,
getFile,
putFile,
lookupProfile
} from 'blockstack';
import Status from './Status.jsx';
const avatarFallbackImage = 'https://mysite/onename/avatar-placeholder.png';
const statusFileName = 'statuses.json'
export default class Profile extends Component {
constructor(props) {
super(props);
this.state = {
person: {
name() {
return 'Anonymous';
},
avatarUrl() {
return avatarFallbackImage;
},
},
username: "",
newStatus: "",
//newTitle: "",
// newEvent: "",
statuses: [],
statusIndex: 0,
isLoading: false
};
this.handleDelete = this.handleDelete.bind(this);
this.isLocal = this.isLocal.bind(this);
}
componentDidMount() {
this.fetchData()
}
handleNewStatusChange(event) {
this.setState({
newStatus: event.target.value,
//newTitle: event.target.value,
//newEvent: event.target.value
})
}
handleNewStatusSubmit(event) {
this.saveNewStatus(
this.state.newStatus,
//this.state.newTitle,
//this.state.newEvent
)
this.setState({
newStatus: "",
//newTitle: "",
//newEvent: "",
})
}
handleDelete(id) {
const statuses = this.state.statuses.filter((status) => status.id !== id)
const options = { encrypt: false }
putFile(statusFileName, JSON.stringify(statuses), options)
.then(() => {
this.setState({
statuses
})
})
}
saveNewStatus(statusText) {
let statuses = this.state.statuses
let status = {
id: this.state.statusIndex++,
text: statusText.trim(),
//textTitle: statusText.trim(),
//textEvent: statusText.trim(),
created_at: Date.now()
}
statuses.unshift(status)
const options = { encrypt: false }
putFile(statusFileName, JSON.stringify(statuses), options)
.then(() => {
this.setState({
statuses: statuses
})
})
}
fetchData() {
if (this.isLocal()) {
this.setState({ isLoading: true })
const options = { decrypt: false, zoneFileLookupURL: 'https://myapi/v1/names/' }
getFile(statusFileName, options)
.then((file) => {
var statuses = JSON.parse(file || '[]')
this.setState({
person: new Person(loadUserData().profile),
username: loadUserData().username,
statusIndex: statuses.length,
statuses: statuses,
})
})
.finally(() => {
this.setState({ isLoading: false })
})
} else {
const username = this.props.match.params.username
this.setState({ isLoading: true })
lookupProfile(username)
.then((profile) => {
this.setState({
person: new Person(profile),
username: username
})
})
.catch((error) => {
console.log('could not resolve profile')
})
const options = { username: username, decrypt: false, zoneFileLookupURL: 'https://myapi/v1/names/'}
getFile(statusFileName, options)
.then((file) => {
var statuses = JSON.parse(file || '[]')
this.setState({
statusIndex: statuses.length,
statuses: statuses
})
})
.catch((error) => {
console.log('could not fetch statuses')
})
.finally(() => {
this.setState({ isLoading: false })
})
}
}
isLocal() {
return this.props.match.params.username ? false : true
}
render() {
const { handleSignOut } = this.props;
const { person } = this.state;
const { username } = this.state;
return (
!isSignInPending() && person ?
<div className="container">
<div className="row">
<div className="col-md-offset-3 col-md-6">
<div className="col-md-12">
<div className="avatar-section">
<img
src={ person.avatarUrl() ? person.avatarUrl() : avatarFallbackImage }
className="img-rounded avatar"
id="avatar-image"
/>
<div className="username">
<h1>
<span id="heading-name">{ person.name() ? person.name()
: 'no name found' }</span>
</h1>
<span>{username}</span>
{this.isLocal() &&
<span>
|
<a onClick={ handleSignOut.bind(this) }>(Logout)</a>
</span>
}
</div>
</div>
</div>
{this.isLocal() &&
<div className="new-status">
<div className="col-md-12">
<textarea className="input-status" name="newStatus"
value={this.state.newStatus}
onChange={e => this.handleNewStatusChange(e)}
placeholder="What's on your mind?"
/>
<input className="input-status" name="newTitle"
value={this.state.newTitle}
onChange={e => this.handleNewStatusChange(e)}
placeholder="your Title"
/>
<input className="input-status" name="newEvent"
value={this.state.newEvent}
onChange={e => this.handleNewStatusChange(e)}
placeholder="Your Event Centre Name"
/>
</div>
<div className="col-md-12 text-right">
<button
className="btn btn-primary btn-lg"
onClick={e => this.handleNewStatusSubmit(e)}
>
Submit
</button>
</div>
</div>
}
<div className="col-md-12 statuses">
{this.state.isLoading && <span>Loading...</span>}
{
this.state.statuses.map((status) => (
<Status
key={status.id}
status={status}
handleDelete={this.handleDelete}
isLocal={this.isLocal}
/>
))
}
</div>
</div>
</div>
</div> : null
);
}
}
Here is just sample part for for status.jsx showing how I successfully return the status:
//some coding...
return (
<div className="status">
<div className="status-text">
{status.text}
/*
{status.textTitle} {status.textEvent}
*/
</div>
</div>
)
You can use the name attribute of the input field to your advantage.
And update your change handler function:
handleNewStatusChange(event) {
this.setState({
[event.target.name]: event.target.value,
})
}
more info on { [key]: value }

formik not changing value of input on event

I cant seem to figure this out.
I have a form that is validated by formik.
When i click the search button, I make an api call to get a list of addresses.
When i click on one of those addresses, I want to populate the inputs with the data from the clicked address.
I can do all of the above except for the last part. I have tried using document.getElementById.innerHTML, setting it in state and having the input controlled by that state object, but i cant seem to get it to populate with any data.
import React, { Component } from 'react';
import { Formik, Form, Field } from 'formik';
import Axios from 'axios';
class CharityAgreement extends Component {
constructor(props) {
super(props);
this.state = {
response: [],
visible: true,
address: ''
}
}
postcodeChange = (e) => {
console.log(e.target.value);
this.setState({ 'postcode': e.target.value })
}
searchPostcode = () => {
this.setState({ 'visible': true });
if (this.state.postcode.length > 0) {
Axios.get('post code api lookup here')
.then(response => {
this.setState({ 'response': response.data });
console.log('response data:', response.data);
})
} else {
}
}
addressClick = (e) => {
console.log('CLICKED ADDRESS:', e.target.innerHTML);
this.setState({ 'visible': false });
}
render() {
const result = this.state.response.map((item) => {
if (this.state.visible === true) {
return (
<p key={item.Id} onClick={this.addressClick} className='lookup-data'>{item.address1Field} {item.address2Field} {item.townField} {item.countyField}</p>
)
} else {
}
})
return (
<div className='body-wrapper'>
<main id='mainContent' className='container'>
<div className='page-content-wrapper'>
<div className='raised-bordered-wrapper'>
<div className='raised-bordered quiz form'>
<Formik
initialValues={{
address_1:'',
}}
validate={(values) => {
const errors = {};
if (!values.address_1) errors.address_1 = 'Required';
return errors;
}}
onSubmit={this.handleSubmit}
render={({
touched,
errors,
values,
handleChange,
handleBlur,
handleSubmit
}) => (
<Form>
<div className='form-row'>
<span className='form-cell-wrapper'>
<label>Postcode Lookup</label>
<Field
name='postcode-lookup'
type='text'
onChange={this.postcodeChange}
/>
<button className='btn' onClick={this.searchPostcode}>Search</button>
</span>
</div>
{result}
<div className='form-row'>
<h5>License Code and Area</h5>
<span className='form-cell-wrapper'>
<label>Address Line 1</label>
<Field
name='address_1'
value={values.address_1}
onChange={handleChange}
id='address'
type='text'
style={{
borderColor:
errors.address_1 && touched.address_1 && "tomato"
}}
/>
</span>
</div>
</Form>
)}
/>
</div>
</div>
</div>
</main>
</div>
)
}
}
export default CharityAgreement;

How to fix inifnity loop?

Hi guys i have this problem. I have input and dropdown I need choose from option dropdown and write value on input but first value was everytime empty. I solved this problem with componentDidUpdate and set locationValue on undefined. After i have sometimes this error.How can I fixed it? I need change lifecycle method or what ?
Here is code
class AccordionForm extends Component {
state = {
value: '',
locationValue: undefined,
};
componentDidUpdate() {
const { nameOptions } = this.props;
if (nameOptions && nameOptions && this.state.locationValue === undefined) {
this.setState({
locationValue: nameOptions[0],
});
}
}
handleChangeInputSelect = ({ target }) => {
this.setState({
locationValue: target.value,
});
};
handleChangeInput = ({ target }) =>
this.setState({
value: target.value,
});
onSubmit = event => {
const { value, locationValue } = this.state;
const { handleSubmitForm } = this.props;
event.preventDefault();
handleSubmitForm(value, locationValue);
this.setState({ value: '' });
};
render() {
const { name, nameOptions } = this.props;
const { value } = this.state;
return (
<Form className="accordion_form" name={name} onSubmit={this.onSubmit}>
<FormGroup className="form-group-locations">
{nameOptions && (
<Input
className="form-input"
required
name={name}
type="select"
onChange={this.handleChangeInputSelect}
>
{nameOptions.map((option, index) => {
return (
<option key={index} value={option}>
{option}
</option>
);
})}
</Input>
)}
<Input
placeholder={`add new ${name}...`}
type="text"
required
name={name}
value={value}
onChange={this.handleChangeInput}
className="form-input"
/>
<Button className="tagBtn" color="success" type="submit">
Add
</Button>
</FormGroup>
</Form>
);
}
}
export default AccordionForm;
This could be happening because at the first instance your nameOptions[0] is undefined. Please update your if statement's conditions like this:
componentDidUpdate() {
const { nameOptions } = this.props;
if (nameOptions && !!nameOptions.length && nameOptions[0] && this.state.locationValue !== nameOptions[0]) {
this.setState({
locationValue: nameOptions[0],
});
}
}

update values in react form input fields

I am new to react and I can fetch the result from form input fields. Now I need to update those values and submit to the backend. I am struggling to find a way to pass all the input field values at once.
constructor(props) {
super(props);
this.state = {
items: [],
isLoaded: false,
data: this.props.location.data
};
}
render() {
return (
<div>
<h2>Update Your Profile</h2>
{items.map(item => (
<Form key={item.uId} onSubmit={this.handleSubmit}>
<label>User Name</label>
<input type="text" defaultValue={item.userName}></input>
<label>Email address</label>
<input type="email" defaultValue={item.email}></input>
</div>
<button type="submit" >Update</button>
</Form>
))}
</div>
);
}
handleSubmit = (e) => {
e.preventDefault();
axios.put('http://localhost:3000/api/user/' + this.state.data, this.state.items).then(response => {
//
});
};
My API call looks like this:
app.put('/api/user/:userId', (req, res, err) => {
User.update(
{ userName: req.body.userName, email: req.body.email },
{
where: {
userId: req.params.userId
}
}
).then(function (rowsUpdated) {
res.json(rowsUpdated)
}).catch(err);
});
How can I modify this code to set a value for this.state.items with all the updated fields values and submit it?
I'd recommend to create a new component to wrap around the <Form /> and move the submit/change event handling to that component for each item. This would allow you to be able to extract individual email/userName for any given <Form /> to send as a PUT to your API endpoint as well as handle the respective input value changes.
Parent Component:
class Parent extends Component {
constructor() {
super();
this.state = {
name: 'React',
items: [
{ uId: 1, email: 'foo#test.com', userName: 'bar' },
{ uId: 2, email: 'baz#test.com', userName: 'foobar' }
]
};
}
render() {
return (
<div>
{this.state.items.map(item =>
<MyForm key={item.uId} item={item} data={this.props.location.data} />)}
</div>
);
}
}
Child/Form Component:
import React, { Component } from 'react';
class MyForm extends Component {
constructor(props) {
super(props);
this.state = {
email: this.props.item.email,
userName: this.props.item.userName
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
// https://reactjs.org/docs/forms.html#handling-multiple-inputs
handleChange(e) {
const { target} = event;
const value = target.type === 'checkbox' ? target.checked : target.value;
const { name } = target;
this.setState({ [name]: value });
}
handleSubmit(e) {
e.preventDefault();
const { email, userName } = this.state;
const body = { email, userName };
const json = JSON.stringify(body);
console.log(json);
// axios.put('http://localhost:3000/api/user/' + this.props.data, json).then(response => {});
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>User Name</label>
<input type="text" defaultValue={this.state.userName}></input>
<label>Email address</label>
<input type="email" defaultValue={this.state.email}></input>
<button type="submit" >Update</button>
</form>
);
}
}
export default MyForm;
Here is an example in action.
Hopefully that helps!

Resources