React - state won't update - reactjs

i am building small react app and i have strange situation that state won't update. Here is example:
class App extends Component {
constructor() {
super();
this.state = {
locale: 'de',
countryList: [],
fetchInProgress: true,
serverError: {},
person: {
salutation: '',
firstName: '',
lastName: '',
birthDate: '',
nationality: '',
address: '',
zipCode: '',
city: '',
country: '',
mobileNumber: '',
email: '',
correspondanceLanguage: '',
}
};
}
componentDidMount() {
this.setState({
fetchInProgress: false
}),()=>console.log('State updated', this.state)
}
}
I tried also using other approaches:
componentDidMount() {
const temp = {...this.state};
temp.fetchInProgress = false;
this.setState(temp),()=>console.log('State updated', this.state)
}
componentDidMount() {
const temp = {...this.state};
temp['fetchInProgress'] = false;
this.setState(temp),()=>console.log('State updated', this.state)
}
But never gets state updated. Any help?

You have syntax errors in all of your approaches. Note that setState() has the following format:
setState(updater, callback)
where updater can either be a function or an object and where callback is a function.
Starting with your initial approach:
this.setState({
fetchInProgress: false
}),()=>console.log('State updated', this.state)
should instead be:
this.setState({
fetchInProgress: false
},()=>console.log('State updated', this.state))
The other code is correct until, again, you get to the setState() part:
this.setState(temp),()=>console.log('State updated', this.state)
should instead be:
this.setState(temp,()=>console.log('State updated', this.state))

Related

`getDerivedStateFromProps` is not updating the state

I am trying to update the state of class component via props that sent from above component,
At first I've set an constructor that fetch the data from the props and place it in the state but that did not work because of the render() did not called.
So I've reed of the function getDerivedStateFromProps which called before render, But I don't know if I'm using it correct.
I'm send an prop as institute from above component and implement the getDerivedStateFromProps() like this:
static getDerivedStateFromProps(nextProps, prevState) {
if (prevState.id !== nextProps.institute.id) { // need to update
return {
id: nextProps.id,
name: nextProps.name,
contactName: nextProps.contactName,
phoneNumber: nextProps.phoneNumber,
city: nextProps.city,
street: nextProps.street,
number: nextProps.number,
deleted: nextProps.deleted
};
}
console.log("null")
return null;
}
I've also set an initState values:
state = {
id: '',
name: '',
contactName: '',
phoneNumber: '',
city: '',
street: '',
number: '',
deleted: '',
}
getDerivedStateFromProps if statement is true but it's not updating the state at all.
I will appreciate any kind of help.
Thanks!

Cannot read property 'files' of undefined for sending multiple images

Code
class Add_Give_Item_Form extends Component {
constructor(props) {
super(props);
this.state = {
// #インプット情報用
info: {
name: '',
owner: '',
keyword1: '',
keyword2: '',
keyword3: '',
bland: '',
state: '未使用、新品',
category: '',
images: [],
detail: '',
},
// Validation用
//  urlは必須項目ではないのでValidationには含めない
message: {
name: '',
keyword1: '',
keyword2: '',
keyword3: '',
state: '',
category: '',
detail: '',
},
allCategory: null,
allBland: null,
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleImageSelect = this.handleImageSelect(this);
}
////
...
////
handleChange = (e) => {
const name = e.target.name;
const value = e.target.value;
const { info, message } = this.state;
this.setState({
info: { ...info, [name]: value },
});
this.setState({
message: { ...message, [name]: this.validator(name, value) },
});
};
handleImageSelect = (e) => {
this.setState({
info: { ...this.state.info, images: [...this.state.info.images, e.target.files] },
});
};
render() {
const { info, message, allCategory, allBland } = this.state;
// setStateが完了するまではnullにする。
if (this.state.allCategory === null || this.state.allBland === null) {
return <CircularProgress />;
} else {
return (
<div>
///////
.....
///////
<label>Images</label>
<input type="file" multiple onChange={this.handleImageSelect} />
What I want to do
I would like to catch each file sent by a user and put into state as this.state.info.images which is an array.
I saw some questions on stackoverflow and then I found some solutions. When I wrote the same code as what I saw, I got an error like below.
cannot read property files of undefined
I should write the same code but I got the error for some reasons.
I may take another way to realize what I want to do, but I want to write readable codes and figure out why it is happening.
I would like you to teach me why this happens and solutions.
Thank you very much.
I just notice I didn't put bind with this.handleImageSelect = this.handleImageSelect(this).
Now it works well.
Thank you very much.

Pass state to page on form submit?

I have a state on one page, and when i submit a form I'd like to redirect to another page with the state of the source page, and populate the state on the new page with the old state on the old page haha if that makes sense. Hopefully my code attempt can explain it better.
class NewFormDetails extends Component {
constructor(props) {
super(props);
this.state = {
language: this.props.language,
siteName: '',
counties: '',
siteAddress: '',
siteEmail: '',
siteNumber: '',
siteCat: '',
openTimes: '',
fees: '',
access: '',
gps: '',
w3w: '',
txtHeader: '',
txtContent: '',
isLoading: false
};
}
validateForm() {
if (this.state.siteName != '' &&
this.state.siteAddress != '' &&
this.state.siteEmail != '' &&
this.state.siteNumber != '' &&
this.state.openTimes != '' &&
this.state.fees != '' &&
this.state.access != '' &&
this.state.gps != '' &&
this.state.w3w != '' &&
this.state.txtHeader != '' &&
this.state.txtContent != '') {
return true;
} else {
return false;
}
}
handleChange = e => {
this.setState({ ...this.state, [e.target.name]: e.target.value });
console.log(this.state);
}
handleSubmit = event => {
event.preventDefault();
/* try {
await this.createSiteDetails({
siteName: this.state.siteName,
siteAddress: this.state.siteAddress,
siteCounty: this.state.counties,
siteNumber: this.state.siteNumber,
siteEmail: this.state.siteEmail,
siteCategory: this.state.siteCat,
siteOpeningTimes: this.state.openTimes,
siteFees: this.state.fees,
siteAccess: this.state.access,
siteGPS: this.state.gps,
siteW3W: this.state.w3w,
siteHeaderText: this.state.txtHeader,
siteContentText: this.state.txtContent
});
this.props.history.push("/");
} catch (e) {
alert(e);
this.setState({ isLoading: false });
} */
console.log(this.state);
this.props.history.push({
pathname:"/newSite/tours",
state:{
value: this.state
}
});
}
And here is the page i redirect to and attempt to get the state from the other page
class NewFormTours extends Component {
constructor(props) {
super(props);
this.state = {
language: this.props.language,
tourName: '',
waypoints: '',
duration: '',
toursTxtHeader: '',
toursTxtContent: '',
siteName: this.siteName,
counties: this.props.counties,
siteAddress: this.props.siteAddress,
siteEmail: this.props.siteEmail,
siteNumber: this.props.siteNumber,
siteCat: this.props.siteCat,
openTimes: this.props.openTimes,
fees: this.props.fees,
access: this.props.access,
gps: this.props.gps,
w3w: this.props.w3w,
detailsTxtHeader: this.props.detailsTxtHeader,
detailsTxtContent: this.props.detailsTxtContent,
};
You can use react router to pass data to new component.
Below discussion should be helpful.
How do i pass state through React_router?

NextJS: Use same component in multiple routes for multiple pages

In my NextJS app, I have a search bar component OrderSearchBar.js and I want to use it in both index.js and /purchases.js pages but with different endpoints.For example,if I click search button on the index.js page,it should post form content to /orders and on the /purchases.js, form content should post to /purchaseDetails.Is there any way to accomplish this?
OrderSearchBar.js
class OrderSearchBar extends Component{
constructor(props) {
super(props);
this.onChangeInput = this.onChangeInput.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
nature: '',
type: '',
searchBy: '',
startDate: '',
endDate: '',
keyword: ''
}
}
onChangeInput(e) {
this.setState({
[e.target.name]: e.target.value
});
}
onSubmit(e) {
e.preventDefault();
const t = {
nature: this.state.nature,
type: this.state.type,
searchBy: this.state.searchBy,
startDate: this.state.startDate,
endDate: this.state.endDate,
keyword: this.state.keyword
}
axios.post('/search', t)..then(res => console.log(res.data));
/*I can do this for single endpoint.but how do I add multiple endpoints
for use in different pages?*/
this.setState({
nature: '',
type: '',
searchBy: '',
startDate: '',
endDate: '',
keyword: ''
});
}
You can differentiate the current location in your orderSearchBar.js
by getting the pathname of window.location object.
onSubmit(e) {
e.preventDefault();
const t = {
nature: this.state.nature,
type: this.state.type,
searchBy: this.state.searchBy,
startDate: this.state.startDate,
endDate: this.state.endDate,
keyword: this.state.keyword
}
const pathName = window && window.location.pathname;
const destination = (pathName === '/purchases') ? '/purchaseDetails' : '/orders'
axios.post(destination, t)..then(res => console.log(res.data));
this.setState({
nature: '',
type: '',
searchBy: '',
startDate: '',
endDate: '',
keyword: ''
});
}
While you could use window property, this might not work if you're using Nuxt.js or other server side rendering, since the window object is not present.
Instead, I suggest you pass a prop down to your component, say:
<component :type="'isPurchaseDetails'">
or for purchases
<component :type="'isPurchases'">

invalid Invalid left-hand side in arrow function parameters (43:13)

hello im a noob in react and am trying to pass the car.id using props to my editcar component so i can update it via firebase , however im getting a an error Invalid left-hand side in arrow function parameters (43:13) any idea how i can pass the car.id to edit function? thanks for the help!
admin_cars.js
<ul className="TaskList">
{
Cars.map(car => (
<tr>
<th scope="row">{car.id}</th>
<td>{car.year}</td>
<td>{car.make}</td>
<td>{car.model}</td>
<td>{car.body_type}</td>
<td>{car.int_color}</td>
<td><img src={car.link} height="92" /> </td>
<td>{car.price}</td>
<td>{car.status ? "Available" : "Sold"}</td>
<td>
<Link to={`/admin/editcar/${this.props.car.id}`}>
<Icon icon={pencil} />
</Link>
</td>
</tr>
))
}
</ul>
edit_car.js
import { CarsRef, timeRef } from './reference';
class EditCar extends Component {
state = {
year: '',
make: '',
model: '',
trim: '',
engine: '',
drive_type: '',
body_type: '',
ext_color: '',
int_color: '',
transmission: '',
price: 0,
sale: 0,
status: true,
vin: '',
link: '',
elect_stab: '',
wireless: '',
seat: '',
keyless: '',
trip_comp: '',
tire_pressure: '',
wiper: '',
id:'',
headlight: '',
alertMsg: false
}
editcar = (e, car.id) => {
alert(this.car.id)
e.preventDefault();
const NewCar= {
body_type: this.state.body_type.trim(),
wiper: this.state.wiper,
headlight: this.state.headlight,
make: this.state.make,
link: this.state.link,
engine: this.state.engine,
transmission:this.state.transmission,
vin:this.state.vin,
seat: this.state.seat,
price: this.state.price,
ext_color: this.state.ext_color,
checked: false,
starred: false,
timestamp: timeRef
};
CarsRef.child().update(NewCar);
this.setState({ body_type: '' });
this.setState({ wiper: '' });
this.setState({ make: '' });
this.setState({link:''});
this.setState({ headlight: '' });
this.setState({price: ''});
this.setState({transmission: ''});
this.setState({engine: ''});
this.setState({vin: ''});
this.setState({ext_color: ''});
this.setState({id: ''})
}
I think this might be related to your editcar method. The second parameter is not valid and you probably meant for it to be car and not car.id, so:
change
editcar = (e, car.id) => {}
to
editcar = (e, car) => {}

Resources