Reputation: 91
Here's the basic layout of the object I'm using (being passed as a prop to the component):
bigObject {
overview: {
*not being used for current concern*
},
code: {
1: {
textArray: [*array of length 4 to 8*],
imgSrc: "string goes here"
},
2: {
textArray: [*array of length 4 to 8*],
imgSrc: "string goes here"
},
3: {
textArray: [*array of length 4 to 8*],
imgSrc: "string goes here"
},
}
}
My constructor:
constructor(props) {
super(props);
this.state = {
projectName: this.props.projectName,
info: bigObject[this.props.projectName]
}
this.renderInfo = this.renderInfo.bind(this);
this.renderText = this.renderText.bind(this);
console.log(this.state.info);
}
What I'm trying to do is iterate through the code object so that for each imgSrc, the text array in the object with it is iterated over to create list elements along side the photo.
renderInfo() {
return Object.keys(this.state.info.code).map(function(key, index) {
return (
<div className="code-snippet" id={name + key} key={key}>
<div className="code-description">
<ul>
{() => this.renderText(key)}
</ul>
</div>
<div className="code-img">
<img src={"/project-images/MongoScraper/" + placeholder[key].img} alt=""/>
</div>
</div>
)
});
}
Each img is rendered exactly how I want, but the renderText method isn't iterating through the textArray like I want:
renderText(key) {
console.log("hello world") //doesn't log
let placeholder = this.state.info.code;
return placeholder[key].text.map(function(keyValue, index) {
return (
<li>{placeholder[key].text[index]}</li>
)
});
}
The render() method:
render() {
return (
<div className="container code-descriptor-div">
{this.renderInfo()}
</div>
)
}
I'm using an arrow function when I call the renderText method because of lexical scoping concerns ("cannot read property of undefined" results from not using the arrow function), but I know the method isn't being called at all because the console isn't logging "Hello world".
When I call the renderText method inside of the render() method, it will render the list elements properly, but doing that doesn't work with how I'm structuring other components.
Is there a way to iterate through the textArray like I want?
Upvotes: 4
Views: 14082
Reputation: 97
You cannot return a new statement from inside an async function such as map() which is already inside your main function. You must pass a callback in the parent function. Try something like this:
function foo(callback){
const bigObject = [{
textArray: [*array of length 4 to 8*],
imgSrc: "string goes here"
}, {
textArray: [*array of length 4 to 8*],
imgSrc: "string goes here"
}];
if(bigObject.length>0){
bigObject.map((obj)=>{
callback(obj);
});
}
}
Now you can call all the value from bigObject inside your render method like so:
render(){
return (
<div>
{this.foo(e){ console.log(e.textArray); }}
</div>
)
}
Upvotes: 0
Reputation: 20614
Change
{() => this.renderText(key)}
to:
{this.renderText(key)}
function
for map.change:
.map(function(key, index) {
to:
.map((key, index) => {
When writing React code, use arrow functions everywhere. It will be a very rare case where you need to use the function
keyword.
Upvotes: 10