I am struggling to find the right way to access the data in my react component.
This is my action creator. I save every row returned from the promise into an array
export function getBlocks(){
console.log("get blocks called");
var blocks = [];
eos.getTableRows(true, "blockboard", "blockboard",
"board").then(function(data){
console.log("data in callback",data);
for(var i = 0; i < data.rows.length; i++){
blocks.push(data.rows[i]);
}
});
console.log("the blocks",blocks);
return {
type: GET_BLOCKS,
payload: blocks
};
}
This is my reducer:
export default function (state = [], action){
console.log('Action received', action);
switch(action.type){
case GET_BLOCKS:
console.log("the received action", action.payload);
return [...state, action.payload];
}
return state;
}
In the component I receive the data but when I try to display it, it doesn't work. It gives me undefined when trying to access a specific row in the array.
import React, {Component} from 'react';
import {connect} from 'react-redux';
class Blocks extends Component {
renderBlocks(blockData){
console.log("Data in renderBlocks Func",blockData);
const alldata = blockData[0];
console.log(alldata);
if(alldata !== undefined){
console.log("alldata ", alldata);
return alldata.map(function(data){
return(
<div key={data.id}>
<h3>{data.text}</h3>
</div>);
});
}
}
render(){
return (
<div>
<h2>Helloooo</h2>
{this.renderBlocks(this.props.blocks)}
<div></div>
</div>
);
}
}
function mapStateToProps({blocks}){
return {blocks};
}
export default connect(mapStateToProps, null)(Blocks);
These are the values for the console.logs that I get in the renderBlocs function.
If I do something like blockData[0][0] to access the data, I get a "Uncaught TypeError: Cannot read property '0' of undefined"
EDIT: 15.9.18 - 14:00 european time
I updated the renderBlocks function to reflect the answer.
renderBlocks(blockData){
console.log("Data that renderBlocks receives, blockData",blockData);
var alldata = blockData[0];
console.log("blockData[0]",alldata);
if(alldata !== undefined){
const newdata = Object.keys(alldata).map(function(k){
return alldata[k];
});
console.log("the new array looks like this", newdata);
console.log(alldata);
}
}
This are the returned data objects:
I found a solution with the help of TeeAttack42. Thank you very much for your help!
Solution
First I updated my action creator and reducers to reflect TeeAttack42s submission:
action creator:
export const getBlocks = async () => {
console.log("get blocks called");
let blocks = [];
await eos.getTableRows(true, "blockboard", "blockboard",
"board").then(function(data){
console.log("data in callback",data);
if(data){
blocks = data.rows;
}
});
console.log("the blocks",blocks);
return {
type: GET_BLOCKS,
payload: blocks
};
}
reducer:
export default function (state = [], action){
console.log('Action received', action);
switch(action.type){
case GET_BLOCKS:
console.log("the received action", action.payload);
return [...state, ...action.payload];
}
return state;
}
Then I could do this in my component and it displayed the text:
renderBlocks(blocks){
if(blocks.length > 0){
return blocks.map(function(data){
return (<div key={data.id}>
<h3>{data.text}</h3>
</div>);
});
}
}
render(){
const {blocks} = this.props;
console.log(blocks);
return (
<div>
<h2>Helloooo</h2>
{this.renderBlocks(blocks)}
</div>
);
}
summary:
I think that earlier approaches failed because of the async behaviour. This discussion helped me to understand https://stackoverflow.com/questions/17546953/cant-access-object-property-even-though-it-exists-returns-undefined. I was confused because console.log showed me something that maybe wasn't even there when I called it.
The output of console.log(anObject) is misleading; the state of the object displayed is only resolved when you expand the > in the console. It is not the state of the object when you console.log'd the object.
By checking the blocks.length I make sure that the props.blocks is reiceived, then I can go on to show the content.