setState not setting state variable React - javascript

I'm trying to set state variable to response data from api call but unable to do so . I have division array in responseJson which i'm trying to set to divisions array in state. I'm getting the responseJson values on console.log but when i'm trying setState({...this.state,divisions:responseJson.division}) i'm not getting any data on console.
state
this.state={
token: data.token,
role: data.role,
userId: data.userId,
organizationId: data.organizationId,
organizationName: data.organization_name,
workspacePP: false,
workspaces: [],
divisions:[],
addWorkspace: null,
isDivisionViewable:false,
divisionName:null
};
function addDivision
addDivision=()=> {
const uri = `${APPURL}/workspace/division/create`;
console.log('dddddd',this.state)
fetch(uri, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.state.token}`
},
body: JSON.stringify({
workspace_id: this.state.workspaces[0].workspace_id,
organization_id: this.state.organizationId,
division:this.state.divisionName
}),
}).then((res)=>res.json()).then(responseJson=>{
if(!responseJson.status){
message.error(responseJson.error);
return;
}
console.log('dddd',responseJson);
this.setState({...this.state,divisions:responseJson.division})
})
console.log(this.state)//returns empty array
}
responseJson
{status: true, division: Array(1), created_at: {…}, user: {…}}
created_at:
updated_at: ["2019-03-09 14:05:26"]
__proto__: Object
division: Array(1)
0: {id: 5, userid: "t863060h", workspace_id: "ROPHV6W", workspace_name:
"workspace", created_at: "2019-03-09 13:39:31", …}
length: 1
__proto__: Array(0)
status: true
user:
created_at: "2019-03-08 18:29:56"
email: "trycatchh#mail.com"
email_verification: 1
id: 1
loginStatus: 0
mobile_otp: 0
mobile_verification: 0
phone: "9632587410"
role: "Admin"
slug: ""
status: 2
team: null
uid: null
updated_at: "2019-03-08 18:29:56"
userid: "t863060h"
username: "tryy catchh"
console.log(this.state)
nName: "tryCatchh", …}
addWorkspace: true
divisionName: "dud"
**divisions**: Array(0)//no data
length: 0
__proto__: Array(0)
isDivisionViewable: true
organizationId: "finalids"
organizationName: "tryCatchh"
role: "Admin"
userId: "t863060h"
workspacePP: false
workspaces: [{…}]
other funtction
showDivision=()=>{
console.log('dddd',this.state.divisions);
}

SetState is asynchronous so To see updated state value you need to
Change
this.setState({...this.state,divisions:responseJson.division})
To
this.setState({
divisions:responseJson.division
}, () => {
console.log(this.state.divisions);//here you will get updated divisions state value
});

Notice your setState is in then function, and will run after the API call response. Your console.log(this.state) will run immediately after calling the API.
if you want to see the final state after the API call, pass a callback func as the second parameter to setState like this:
this.setState({ divisions:responseJson.division }, () => console.log(this.state))
note: you don't need to destructure the state when calling setState, React does it for you already.

Related

TypeError: Cannot read property 'map' of undefined but state has been stored

I am trying to get a specific team data from the database and store it in a state. But when I map an array inside that data it returns an error. When I console log my state it returns the data below
createdAt: "2021-03-19T13:36:22.868Z"
gameEvent: "basketball"
players: Array(5)
0: {_id: "605ea59c5cdf492b48987107", name: "Jerry Ale", jerseyNumber: "12"}
1: {_id: "605ea59c5cdf492b48987108", name: "Judel Agur", jerseyNumber: "14"}
2: {_id: "605ea59c5cdf492b48987109", name: "qwe", jerseyNumber: "12"}
3: {_id: "605ea59c5cdf492b4898710a", name: "qwe", jerseyNumber: "12"}
4: {_id: "605ea59c5cdf492b4898710b", name: "qwe", jerseyNumber: "12"}
length: 5
__proto__: Array(0)
teamName: "Balilihan"
updatedAt: "2021-03-27T03:25:16.148Z"
__v: 0
_id: "6054a8d63fec5c24389624ac"
I have an useEffect to gather this;
useEffect(() => {
const getTeam = async () => {
try {
const { data } = await fetchContext.authAxios.get('get-all-teams');
setIsLoaded(true);
if (isLoaded === true) {
setCurrentTeam(data.find((team) => team._id === row._id));
}
} catch (err) {
console.log(err);
}
};
getTeam();
}, [fetchContext, row, isLoaded]);
and I map the players array in a new variable because I want a controlled inputs for my form because I am updating the data. I am using Formik by the way
let playersOfTeam = currentTeam.players.map((player, index) => [
{
name: player.name,
jerseyNumber: player.jerseyNumber,
},
]);
But when I just get a specific value like the teamName it returns the teamName and when I console log currentTeam.players it returns what I expected to get. I am confused why I get this kind of error
Your data is undefined when the component is first mounted. This is because useEffect runs after render.
So adding a null check is the solution. Personally I prefer optional chaining. Simply change to:
let playersOfTeam = currentTeam?.players?.map((player, index) => [
{
name: player.name,
jerseyNumber: player.jerseyNumber,
},
]);

Added new Object to key from Object returned from Fetch & need to get new added values back out

I have JSON I am getting from an API and once that data is fetched, I am using another API to get geocode values and adding that to the object.
Here is the initial object after fetching:
{ approved: 1
body: "sample comments being made. "
categories: (4) [{…}, {…}, {…}, {…}]
created_at: "2020-12-18T19:38:43.000000Z"
email: "janedoe#gmail.com"
geocode: null
id: 7
image_id: "7"
is_moderated: 1
updated_at: "2020-12-21T20:57:04.000000Z"
zip: "60611"
}
Then I am using this loop to use each object's zip to get Geocoding info and add it to each object.
for (const property in data) {
getLocationInformation(data[property]);
const allApprovedComments = createCommentElement(data[property]);
commentContentParent.append(allApprovedComments);
}
This is what the getLocationInformation function looks like:
function getLocationInformation(comment) {
const fullPath = geoCode + '?address=' + comment.zip + '&key=' + geocodeApi;
fetch(fullPath)
.then(function fetchResponse(response) {
return response.json();
})
.then(function parseData(data) {
comment.geocode = {
county: data.results[0].address_components[2].long_name,
state: data.results[0].address_components[3].long_name,
stateAbbrv: data.results[0].address_components[3].short_name,
lat: data.results[0].geometry.location.lat,
lng: data.results[0].geometry.location.lng,
};
})
.catch(function fetchError(error) {
return error;
});
}
Then this is what the object that is returned:
{ approved: 1
body: "sample comments being made. "
categories: [{…}]
created_at: "2020-12-18T19:38:43.000000Z"
email: "janedoe#gmail.com"
geocode: {
county: "Cook County",
state: "Illinois",
stateAbbrv: "IL",
lat: 41.8925085,
lng: -87.61616959999999
},
id: 7
image_id: "7"
is_moderated: 1
updated_at: "2020-12-21T20:57:04.000000Z"
zip: "60611"
}
While, I am able to access the body key and all others, even if console.log(object) shows the geocode key to have values when I try to access the key like: object.geocode the value returned is always null. I don't understand why this is happening and any help with getting past this issue is appreciated!

forEach nested to match

Here i made a code.
let StaffParsed = JSON.parse(params.StaffJson);
console.log(StaffParsed)
Here is the result below fo console log.
Object
cellPhoneNo: "1234567890"
createdBy: "1"
createdDate: "2020-05-09T17:26:31.743"
email: "ravi#email.com"
fax: "1234567890"
firstName: "Ravi"
id: 1004
lastName: "Nikam"
phoneNo: "1234567890"
profilePic: ""
sendEmail: false
sendPhone: false
status: "3"
title: "Mr."
type: "2"
updatedBy: "1"
updatedDate: null
username: "ravi109"
__proto__: Object
I have this model created here is the code below.
public StaffModel : Staff = new Staff();
console.log(this.StaffModel);
Its console log result is below.
Staff
CellPhoneNo: 0
CnfPassword: ""
CreatedBy: ""
CreatedDate: null
Email: ""
Fax: 0
FirstName: ""
FormStaffGroup: FormGroup {validator: null, asyncValidator: null, pristine: true, touched: false, _onCollectionChange: ƒ, …}
Id: null
LastName: ""
Password: ""
PhoneNo: 0
ProfilePic: ""
SendEmail: false
SendPhone: false
Status: "0"
Title: ""
Type: "0"
UpdatedBy: ""
UpdatedDate: null
UserName: ""
__proto__: Object
enter code here
Now i want to match with the above first object list with the second list and update the second list model, so far i have tried this code.
Object.keys(StaffParsed).forEach(function(keyParsed) {
Object.keys(this.StaffModel).forEach((keyModel: string) => {
if(keyParsed == keyModel){
keyParsed = this.StaffModel[keyModel];
}
});
});
But in return, it shows error like this .
Your problem is this part:
... .forEach(function(keyParsed) {
Object.keys(this.StaffModel)
this does not propagate into functions like that. As such, the this inside the function has a different value from the this in the outside function.
If you want the function to inherit the this of the outside scope, use an arrow function instead. ((keyParsed) => { instead of function(keyParsed) {)
In your code this in this.StaffModel[keyModel] may refer to the function not global.
Try this:
let that = this;
Object.keys(StaffParsed).forEach(function (keyParsed) {
Object.keys(that.StaffModel).forEach((keyModel: string) => {
if (keyParsed == keyModel) {
keyParsed = that.StaffModel[keyModel];
}
});
});

TypeError: prevState.blockHash is not iterable

I was trying to update the objects stored in an array. but getting TypeError: prevState.blockHash is not iterable.
here is my constructor
constructor(props) {
super(props)
this.state = {
dir:"",
account: '',
name: [],
fido: [{
logIndex: [],
transactionIndex: [],
transactionHash: [],
blockHash: []
}],
loading: true
}
I am setting state in this manner-
showusingBot= () => {
this.setState(this.initialState)
this.state.instance.events.Artworkcreated({
filter: { purchased: false},
fromBlock: 0
}).on('data', event => {
this.setState(prevState =>({
fido:[...prevState.fido.map({blockHash: [
...prevState.blockHash,
event.blockHash
]} )]}));
})
}
my ABI response on console is a follows.
{logIndex: 0, transactionIndex: 0, transactionHash: "0x94f6d8671988ceb8ef1da862257637a198f4afefc3aef6cf3eb992dfcafb0eb1", blockHash: "0xd26937f8535a335663c9af57335f7cc783aba0e9e376408cbb92c1b3f1b28166", blockNumber: 20, …}
logIndex: 0
transactionIndex: 0
transactionHash: "0x94f6d8671988ceb8ef1da862257637a198f4afefc3aef6cf3eb992dfcafb0eb1"
blockHash: "0xd26937f8535a335663c9af57335f7cc783aba0e9e376408cbb92c1b3f1b28166"
blockNumber: 20
address: "0x20B40e09b75a21E0B857F695dE5De92a5A5b5AD0"
type: "mined"
id: "log_0d967aac"
returnValues: Result
0: "1"
1: "bhavin"
2: "masterpiece"
3: "1000000000000000000"
4: "100"
5: "200"
6: "blah blah blah!!"
7: "0x04f78093E2a1C07BF6c4527Aaa00807d3132A1Df"
8: false
id: "1"
Artistname: "bhavin"
Artname: "masterpiece"
price: "1000000000000000000"
width: "100"
height: "200"
Description: "blah blah blah!!"
owner: "0x04f78093E2a1C07BF6c4527Aaa00807d3132A1Df"
purchased: false
__proto__: Object
event: "Artworkcreated"
signature: "0xf912339172a3b7eda9cb10ecdef181d10a74fc4411fe5d7e62f550ef3698d845"
raw: {data: "0x000000000000000000000000000000000000000000000000…16820626c6168212100000000000000000000000000000000", topics: Array(4)}
__proto__: Object
I need to push a string to the array blockHash.
Your whole fido map callback is incorrect, it's supposed to take a function, you are passing an object.
this.setState(prevState =>({
fido:[...prevState.fido.map({blockHash: [
...prevState.blockHash,
event.blockHash
]} )]}));
})
Correct syntax is map((current, index, originalArray) => {...}).
But I don't think you need to map anything, I think you just need to spread the previous state's fido array and add the new element
this.setState(prevState =>({
fido:[...prevState.fido, event.blockHash]
}));
Edit 1
Since fido is static, as you say, I suggest to instead just store its properties in an object, like you do with it currently as an element in an array.
this.state = {
dir:"",
account: '',
name: [],
fido: {
logIndex: [],
transactionIndex: [],
transactionHash: [],
blockHash: []
},
loading: true
}
Now, when updating the fido state, spread in the previous state and the blockHash array with new element
this.setState(prevState =>({
fido: {
...prevState.fido,
blockHash: [...prevState.fido.blockHash, event.blockHash]
},
}));
OFC, if you wanted/needed to keep it as-is, you need to access the element correctly
this.setState(prevState =>({
fido: [{
...prevState.fido[0],
blockHash: [...prevState.fido[0].blockHash, event.blockHash]
}],
}));
blockHash does not exist in state, it only exists in in the objects of state.fido. In your setState you need to access blockHash from each element of fido instead accessing it from the overall state.

How to update value of a specific key in array of objects in react state?

I'm creating a user role management form like this:
Whenever the user checks or unchecks a permission, I'm trying to put that in the state so that I can send it to my backend server and update the DB.
I'm storing all the rows info in the state in componentWillReceiveProps:
componentWillReceiveProps(nextProps){
if(nextProps.users.items){
this.setState({
userobj : nextProps.users.items['users']
});
const userarr = []
nextProps.users.items['users'].map((i) => {
userarr.push({"employeeid" : i['employeeid'] , "isadmin": i['isadmin'], "isreports" : i['isreports'], "ischarts": i['ischarts'], "ischathistory": i['ischathistory']})
});
this.setState({"list" : userarr});
}
}
Now the state is:
list: Object(4)
​​
0: Object { employeeid: "12345", isadmin: false, isreports: true, … }
​​
1: Object { employeeid: "12346", isadmin: false, isreports: true, … }
​​
2: Object { employeeid: "12347", isadmin: false, isreports: true, … }
​​
3: {…}
There is an onClick event for each checkbox:
<Table.Td>{rows['isadmin'] ? <Checkbox id={rows['employeeid']} name="isadmin" defaultChecked onChange={this.handleChange}></Checkbox> : <Checkbox id={rows['employeeid']} name="isadmin" onChange={this.handleChange}></Checkbox>}</Table.Td>
And this is the code for handleChange:
handleChange(id) {
const checked = id.target.checked;
const empid = id.target.id;
const name = id.target.name;
this.setState(prevState => ({
list: {
...prevState.list,
[this.getIndex(empid, this.state.list, 'employeeid')]: {
...prevState[this.getIndex(empid, this.state.list, 'employeeid')],
[name] : checked
},
}
}));
}
The result is:
list: Object(4)
​​
0: Object { isadmin: true }
​​
1: Object { employeeid: "12346", isadmin: false, isreports: true, … }
​​
2: Object { employeeid: "12347", isadmin: false, isreports: true, … }
​​
3: {…}
What I need to achieve is:
list: Object(4)
​​
0: Object { employeeid: "12345", isadmin: true, isreports: true, … }
​​
1: Object { employeeid: "12346", isadmin: false, isreports: true, … }
​​
2: Object { employeeid: "12347", isadmin: false, isreports: true, … }
​​
3: {…}
I'm new to React and Redux. Any help is appreciated. Thanks in advance. ☺
Replace this:
this.setState(prevState => ({
list: {
...prevState.list,
[this.getIndex(empid, this.state.list, 'employeeid')]: {
...prevState[this.getIndex(empid, this.state.list, 'employeeid')],
[name] : checked
},
}
}));
With this:
this.setState(prevState => ({
list: {
...prevState.list,
[this.getIndex(empid, this.state.list, 'employeeid')]: {
...prevState.list[this.getIndex(empid, this.state.list, 'employeeid')],
[name] : checked
},
}
}));
try updating your handleChange method to this
handleChange(id) {
const checked = id.target.checked;
const empid = id.target.id;
const name = id.target.name;
this.setState(prevState => ({
let list = prevState.list
let user = prevState.list.filter(user => user.employeeid == id)
const userIndex = prevState.list.indexOf(user)
user = {
...user,
isadmin: true
}
list.splice(userIndex, 1) //remove the old user
list.splice(userIndex, 0, user) //put the updated user at same index
this.setState({list})
}));
}

Categories

Resources