How to get a data after react select using axios and ReactJS? - javascript

I am newbie on ReactJS, I want to get a Price value just after the select of the Product name by react select and display it.
My method :
constructor(props) {
super(props);
this.state = {
PrixV: ""
}
PrixDisplay(selectprdt) {
return axios.get("/app/getPrixprod/" + selectprdt).then(response => {
if (response && response.data) {
this.setState({
PrixV: response.data
});
}
console.log(response.data)
}).catch(error => {
console.error(error);
});
}
I try to read this value by :
<p>{this.state.PrixV} </p>
When I run it, nothing is displayd on the Price column and after I select the product name, I get :
Objects are not valid as a React child (found: object with keys {PrixV}). If you meant to render a collection of children, use an array instead.
in p (at AjouterFacture.js:383)
And the console returns :
[{…}]0: {PrixV: "250.000"}length: 1__proto__: Array(0)
How can I read and display it ?

You must use the map, try to change the code like this :
constructor(props) {
super(props);
this.state = {
Prix: []};
render() {
let {
Prix
} = this.state.Prix;
return (
<td>
{ this.state.Prix.map((pr, k) =>
<p key={k} >{pr.PrixV} </p>
)}
</td>
);}
PrixDisplay(selectprdt) {
return axios.get("/app/getPrixprod/" + selectprdt).then(response => {
if (response && response.data) {
this.setState({
Prix: response.data
});
}
}).catch(error => {
console.error(error);
});
}
I hope that's will be helpful.

constructor(props) {
super(props);
this.state = {
mydata: ''
};
productNameSelected(selectprdt) {//not sure from where you will get selectprdt variable , but something like this will work
axios.get("/app/getPrixprod/" + selectprdt).then(response => {
if (response && response.data) {
this.setState( {mydata : response.data});
}
console.log(response.data)
})
}
<p>{this.state.mydata} </p> //my data should not be a object , so you need to make string if you wnat to directly use it here
Edit
I can see you are able to get the response , but react still gives error:-
change the paragrah code to
<p>{this.state.PrixV[0].PrixV} </p>
Or The good way will be to set the data properly so
let paragrah be same
<p>{this.state.PrixV} </p>
PrixDisplay(selectprdt) {
return axios.get("/app/getPrixprod/" + selectprdt).then(response => {
if (response && response.data && response.data[0]) {
this.setState({
PrixV: response.data[0].PrixV
});
}
console.log(response.data)
}).catch(error => {
console.error(error);
});
}
You are getting the error because currently you are getting PrixV as an array(object) not a primitive data type.
Hope this solves the issue.

Related

React Redux functional component updating state not working

My data looks like this:
{
'004': [
{
year_week: '2020-W1',
actual_bank_amount: '6500000',
ext_in_rental_income: '',
ext_in_tax_refund: '',
ext_in_dividends_income: ''
},
{
year_week: '2020-W2',
actual_bank_amount: '6500000',
ext_in_rental_income: '',
ext_in_tax_refund: '',
ext_in_dividends_income: ''
}
],
'007': [
{
year_week: '2020-W22',
actual_bank_amount: '65050000',
ext_in_rental_income: '30000',
ext_in_tax_refund: '',
ext_in_dividends_income: ''
}
]
},
I am trying to update say date for year_week '2020-W1' in '004'.
No problem with action and reducer but data is not updated in the list.
Below is my reducer:
case 'UPDATE':
state.planningData[action.payload.currentSite].map((item, index) => {
if (item.year_week === action.payload.data.year_week) {
return Object.assign({}, item, action.payload.data);
}
return item;
});
console.log(state)
return {
loading: true,
planningData: state.planningData,
error: ''
}
What I am doing wrong please. Btw when I do console log or run redux extension I see the updated state.
Below is my action creator:
export const update = (data) =>
(dispatch, getState) => {
console.log("Update action called" + JSON.stringify(data))
const currentSite = getState().sites.currentSite;
dispatch({
type: 'UPDATE',
payload: {
data: data,
currentSite: currentSite
}
});
};
btw I am calling it from a editable cell component on "enter" and blur event below is my code
const save = async e => {
try {
const values = await form.validateFields();
toggleEdit();
dispatch(update({ ...record, ...values }));
} catch (errInfo) {
console.log('Save failed:', errInfo);
}
};
This isn't pretty but it works. You had a bit of nested data in your state and it wasn't being updated properly.
case "UPDATE":
let updatedPlanningData = {};
for (let prop in state.planningData) {
if (prop === action.payload.currentSite) {
updatedPlanningData[action.payload.currentSite] = state.planningData[
action.payload.currentSite
].map((item, index) => {
if (item["year_week"] === action.payload.data.year_week) {
return Object.assign({}, item, action.payload.data);
}
return item;
});
} else {
updatedPlanningData.prop = state.planningData[prop];
}
}
return {
loading: true,
planningData: updatedPlanningData,
error: ""
};
Here is example code in codesandbox
Edit: more compact solution
let updatedPlanningData = {...state.planningData};
updatedPlanningData[action.payload.currentSite].map((item, index) => {
if (item["year_week"] === action.payload.data.year_week) {
return Object.assign(item, action.payload.data);
}
return item;
});

Vue.js: Data is not reactive and not correctly updated within a method

I have a custom component which receives a list of filters in order to display just the doctors that the user has selected:
<DoctorsSidebarFilter #update-view='showFilteredDoctors'></DoctorsSidebarFilter>
Next, in my main component, I'm using this to display the doctors:
<v-flex
v-for="doctor in allDoctors"
:key="doctor.first_name"
xs12
sm6
md4
>
And here's my data:
export default {
data: () => ({
allDoctors:[],
}),
methods: {
fetchDoctors(){
//Retrieve doctors
this.$store.dispatch(RETRIEVE_DOCTORS)
.then(
response => {
this.allDoctors = response;
}
)//TODO-me: Handle the error properly!
.catch(error => {
console.log(error);
});
},
showFilteredDoctors(filters){
let result = [];
this.fetchDoctors();
console.log('1:' + " " + JSON.stringify(this.allDoctors));
if (filters.length > 0) { // If Array is not empty then apply the filters
console.log('2');
this.allDoctors.forEach(function(e) {
if(filters.some(s => s.specialty === e.specialty || s.city === e.city)) {
result.push(e);
}
});
console.log('3:' + " " + JSON.stringify(result));
this.allDoctors = [...result];
console.log('4:' + " " + JSON.stringify(this.allDoctors));
}
}
},
mounted() {
this.fetchDoctors();
}
}
The problem is that eventhough my filtering works correctly and I can see from console.log('4:' + " " + JSON.stringify(this.allDoctors)); that this.allDoctors contains the new, filtered list; this is never displayed on screen.
Instead I see the default list of doctors that I've fetched from my API. Using vue devtools I can see that the this.allDoctors is momentarily updated with the correct values but then it goes back to the default ones.
As #user1521685 has already explained, the call to fetchDoctors is asynchronous so it'll complete after you've performed the filtering.
Typically you'd do something like this using a computed property instead and only make the server call once.
export default {
data: () => ({
allDoctors: [],
filters: []
}),
computed: {
filteredDoctors() {
const allDoctors = this.allDoctors;
const filters = this.filters;
if (filters.length === 0) {
return allDoctors;
}
return allDoctors.filter(doctor => {
return filters.some(filter => filter.specialty === doctor.specialty || filter.city === doctor.city);
});
}
},
methods: {
fetchDoctors(){
//Retrieve doctors
this.$store.dispatch(RETRIEVE_DOCTORS)
.then(
response => {
this.allDoctors = response;
}
)//TODO-me: Handle the error properly!
.catch(error => {
console.log(error);
});
},
showFilteredDoctors(filters){
this.filters = filters;
}
},
mounted() {
this.fetchDoctors();
}
}
In your template you'd then use:
v-for="doctor in filteredDoctors"
fetchDoctors is async, so in showFilteredDoctors you fetch the doctors, then set the filtered array and then the thenable in fetchDoctors kicks in and overrides the doctors again: this.allDoctors = response.
You'd have to return the Promise in fetchDoctors and use it in showFilteredDoctors like so:
this.fetchDoctors().then(() => /* do the filtering */)
EDIT: Return the Promise like this:
return this.$store.dispatch(RETRIEVE_DOCTORS).then().catch()

vue.js component not updated after vuex action on another component

I've a component which render a booking table; When I update my store in another component, the table isn't updated (but the store does and so the computed properties; My guess is that the problem is related to the filter not being updated but I'm not sure at all.
To do so, I've a vuex store:
...
const store = new Vuex.Store({
state: {
bookings: [],
datesel: '',
},
getters: {
bookings: (state) => {
return state.bookings
},
},
mutations: {
SET_BOOKINGS: (state, bookings) => {
state.bookings = bookings
},
},
actions: {
setBookings: ({commit, state}, bookings) => {
commit('SET_BOOKINGS', bookings)
return state.bookings
},
}
})
export default store;
The table is basically a v-for with a filter:
<template v-for="booking in getBookings( heure, terrain )">
Where getBookings is a method:
getBookings(hour, court) {
return this.$store.state.bookings.filter(booking => booking.heure == hour && booking.terrain == court);
}
I've another component which will update my bookings state through a method:
bookCourt() {
axios.post('http://localhost/bdcbooking/public/api/reservations/ponctuelles',
{
date: this.datesel,
membre_id: '1',
heure: this.chosenHour,
terrain: this.chosenCourt,
saison_id: '1'
})
.then(response => {
// JSON responses are automatically parsed.
console.log(response.data);
})
.catch(e => {
this.errors.push(e)
})
axios.get('http://localhost/bdcbooking/public/api/getReservationsDate?datesel=' + this.datesel)
.then(response => {
// JSON responses are automatically parsed.
console.log(response.data);
this.bookings = response.data;
})
.catch(e => {
this.errors.push(e)
})
$(this.$refs.vuemodal).modal('hide');
}
While this.bookings is a computed property:
computed: {
bookings: {
get () {
return this.$store.getters.bookings
},
set (bookings) {
return this.$store.dispatch('setBookings', bookings)
console.log('on lance l action');
}
}
}
Your table is not updated because getBookings is a simple method and hence the method won't be fired again based on vuex state changes.
You can make this getBookings method as an computed property that returns filtered results and will also upadte on state changes.

How to update values in table with this.state?

I make a component, which show information from database in table. But this information with filters.
Filtering can be by event type and by participant (id: integer type).
When I click the button, I call handleShowClick(). In this function I check: if value of type event isn't null, I get from database events with this type. if value of type event is null, I get all events.
After this I check a participant value. If value isn't null, I call function, which search which events are include this participant. Data from this.state.event show in table in another component.
I haven't problems with event type. But I have problem with participant. When I choose one of participant, table shows correct data for a split second. After this return to prev state (without filter by participants).
How can I fix this issue? I set state to event only in this component
class TestPage extends Component {
constructor(props) {
super(props);
this.state = {
event: [],
searchByType: null,
searchByParticipant: null,
participantToEvent: []
};
this.handleShowClick = this.handleShowClick.bind(this);
this.onHandleEventByTypeFetch = this.onHandleEventByTypeFetch.bind(this);
this.handleParticipantSearch = this.handleParticipantSearch.bind(this);
this.onHandleEventFetch = this.onHandleEventFetch.bind(this);
}
handleShowClick() { // onClick
if (this.state.searchByType !== null) {
this.onHandleEventByTypeFetch(); // select * from ... where type=...
} else {
this.onHandleEventFetch(); // select * from ...
}
if (this.state.searchByParticipant !== null) {
this.handleParticipantSearch();
}
}
handleParticipantSearch() {
const list = [];
this.state.participantToEvent.map(itemP => { // participantToEvent is binding table
if (itemP.parid === this.state.searchByParticipant) {
this.state.event.map(itemEvent => {
if (itemEvent.id === itemP.eventid) {
list.push(itemEvent);
}
});
}
});
console.log(list); // here I see array with correct result
this.setState({ event: list });
}
onHandleEventFetch() {
fetch( ... , {
method: 'GET'
})
.then((response) => {
if (response.status >= 400) {
throw new Error('Bad response from server');
}
return response.json();
})
.then(data => {
if (data.length === 0) {
alert('nothing');
} else {
this.setState({
event: data
});
}
});
}
onHandleEventByTypeFetch() {
fetch( ... , {
method: 'GET'
})
.then((response) => {
if (response.status >= 400) {
throw new Error('Bad response from server');
}
return response.json();
})
.then(data => {
if (data.length === 0) {
alert('nothing');
} else {
this.setState({
event: data
});
}
});
...
}
}
Structure of this.state.event:
[{id: 1, name: 'New event', participant: 5, type: 10}, ...]
Structure of this.state.participantToEvent:
[{id: 1, idparticipant: 5, idevent: 1}, ...]
this.setState(...this.state,{ event: list });
I think this would solve your problem. Because you clear every item except for {event:list} by not copying the previous state.
Edit:
You should put
...this.state
to onHandleEventByeTypeFetch and onHandleEventFetch. Without them when you click handleShowClick one of those two functions always work and clears searchByParticipant data from the state by not copying the previous state.
The reason for you see the correct data for a short time is all about async nature of the state.

Getting Object: "undefined" on React

I am a newbie in react JS and I am trying to pull data from a url in Json format.
I did the following but I keep on getting a feeback at the console as
Rovers: undefined.
How do I go about it when am supposed to get something like
Rovers:[object, object, object]
class App extends React.Component {
constructor(props){
super(props);
this.state={rovers:[]};
}
componentWillMount(){
api.getRovers().then((response) =>{
this.setState({
rovers: response.rovers
});
});
}
render() {
console.log("Rovers: ", this.state.rovers);
}
and this is where am calling the json link
var api={
getRovers(){
var url='https://jsonplaceholder.typicode.com/posts/1';
return fetch(url).then((response)=> response.json());
}
};
module.exports=api;
The endpoint replies with object that does not include rovers. However, it includes : id, userId, title and body
That's why response.rovers is undefined. Then this.state.rovers is the same
So , you might mean body instead of rovers , in this case , replace:
componentWillMount(){
api.getRovers().then((response) =>{
this.setState({
rovers: response.rovers
});
});
}
By :
componentWillMount(){
api.getRovers().then((response) =>{
this.setState({
rovers: response.body.split('\n')
});
});
}

Categories