I'm trying to render a list, but when I try and map over the list I can not access each individual element, because I ReferenceError saying that 'e' is undefined. Am I writing this correctly?
render() {
return (
<div>
{console.log(Object.keys(this.props.emojis))} --> Returns the correct list
Object.keys(this.props.emojis).map(e => (
{console.log("EMOJI: ",e)}
<Emoji emote={e} />
))
</div>
)
}
Write it like this, it will work:
render() {
return (
<div>
{
Object.keys(this.props.emojis).map((e,i) => {
console.log("EMOJI: ",e);
return <Emoji key={i} emote={e}/>
})
}
</div>
)
}
Changes:
You are already inside a map function, so no need to use {} for console.log.
You are using () with map function and inside () you are using 2 statement, that is not allowed with (), if you want to do some calculation always use {}, and return something inside it.
Suggestion: Always assign key whenever creating the ui items dynamically.
Let me know if you need any help.
See if this work for you.
logging(e) {
console.log("EMOJI: ", e);
}
render() {
return (
<div>
Object.keys(this.props.emojis).map(e => (
this.logging(e);
<Emoji emote={e} />
))
</div>
)
}
Related
In the code snippet below, I'd like to move this function out of jsx and wrap into useCallback.
{suggestedTags.length ? (
<div className={classes.tagSuggestionWrapper}>
{suggestedTags.map((tag) => {
return (<div key={tag}
onClick={() => { selectTag(tag) }}>{tag}</div>
);
})}
</div>
) : null }
Otherwise, a new function is created for every element on every render.
I understand that this may complicate the code, and may not be advisable. But I have to do it. I ask for your advice
You can do:
const selectTag = useCallback((tag) => {
setTags((prevState) => [...prevState, tag]);
setSuggestedTags([]);
setInput("");
}, [])
Little about useCallback
Bare in mind that if you had used any state variable, or prop, you should have included that in the dependency array. An empty dependency array makes sure selectTag reference will stay the same once the component mounts.
And no dependency array is the same as not using useCallback at all
Removing the arrow function
You can remove the arrow function by passing the value by using the onClick event function:
const selectTag = (event) => {
const tag = event.target.name
setTags((prevState) => [...prevState, tag]);
setSuggestedTags([]);
setInput("");
}
return (
{suggestedTags.length ? (
<div className={classes.tagSuggestionWrapper}>
{suggestedTags.map((tag) => {
return (<div key={tag}
name={tag}
className={classes.tagSuggestion}
onClick={selectTag}>{tag}</div>
);
})}
</div>
) : null }
</div>
);
I'm following the react js tutorial, and I keep running into this issue
import React from "react";
import NewsCard from "../NewsCard/NewsCard";
const NewsCards = ({ articles }) => {
return (
<div>
{articles.map((article, i) => {
<NewsCard />;
})}
</div>
);
};
export default NewsCards;
Seems like your articles does not have default value as [].
You can change as follow. And you should give key attribute when using map function.
const NewsCards = ({ articles }) => {
const data = articles ? articles : []
return (
<div>
{data.map((article, i) => {
<NewsCard key={article.id}/>;
})}
</div>
);
};
Probably articles is not initialized when you try to map throught it. Try this:
{articles?.map((article, i) => {
<NewsCard />;
})}
OR
{articles && articles.map((article, i) => {
<NewsCard />;
})}
</div>
That way you will first make sure if articles exist
This means that the articles prop is undefined.
There are several ways to solve this. The first and easiest way is by implementing the following logic:
{articles?.length ? articles.map((article, i) => <NewsCard />) : "There are no articles here."}
Another way to solve this is by implementing React proptypes - you can read about this here.
Third and "hardest" (but probably best) way to solve this is by using a static type checking tool. Flow comes to mind, but you can use TypeScript too.
If you still need help, just like what the previous answers said, make sure that articles is initialized/defined by using the && operator to make that check. Also, based upon what you wrote, the map method is returning undefined since you specified a function body (using the function body bracket notation {} ) without a return statement. So instead write the map method like this:
<div>
{articles && articles.map((article, i) => <NewsCard />)}
</div>
or like this:
<div>
{articles && articles.map((article, i) => {
return <NewsCard />
})}
</div>
The first example implies an implicit return since an arrow function is being used and a function body is not present (there are no function body brackets { }).
I have the following component:
function Params(props) {
const { Parameters } = useFetchParams();
return (
<div className='Params'>
{
Parameters && Parameters.map(parameter => {
const { Name, Value } = parameter;
if (Name.includes(props.filter)) {
return (
<div className='Param' key={Name}>
<p>{Name}</p>
<p>{Value}</p>
</div>
)
}
})
}
</div>
)
}
I want to only display "Parameters" that include the text I'm passing in from props. You can see I'm currently using an if statement for this, and it seems clunky. I'm wondering if it's possible to map and filter over this array at the same time.
I've tried sticking filter at the end of the map but it returns an error.
Thanks for looking
Like #Yevgen Gorbunkov suggests, what you're doing is fine, filtering before mapping is actually not faster, although it is perhaps, more readable.
But yes, it is possible to do that. Like this:
function Params(props) {
const { Parameters } = useFetchParams();
return (
<div className='Params'>
{
Parameters && Parameters.filter(parameter => parameter.Name.includes(props.filter))
.map(parameter => {
const { Name, Value } = parameter;
return (
<div className='Param' key={Name}>
<p>{Name}</p>
<p>{Value}</p>
</div>
)
})
}
</div>
)
}
I have this function
renderCompanies() {
if (this.props.companies)
return [
<div>
Dashboard hello <div>{this.renderProfile()}</div>
<div>
{this.props.companies.map(function(item, i) {
return (
<div>
<div
key={i}
onClick={item => {
this.setState({ currentCompany: item });
}}
>
{i}: {item.name}
</div>
<button>Delete Company</button>
</div>
);
})}
</div>
<AddCompanyPopUp />
</div>
];
}
I want to loop though this.props.companies and render a list of items. I want a user to be able to click on a specific item and have the item be saved to state.
This function runs inside another funtion
renderEitherMenuOrCompanyList() {
if (this.state.currentCompany) {
return <Menu companies={this.state.currentCompany} />;
} else {
return <div>{this.renderCompanies()}</div>;
}
}
Both are already bound to this
this.renderCompanies = this.renderCompanies.bind(this);
this.renderProfile = this.renderProfile.bind(this);
this.renderEitherMenuOrCompanyList = this.renderEitherMenuOrCompanyList.bind(this)
The renderEitherMenuOrCompanyList function is being called inside the render react function/method.
My problem is that I cannot set the state from the renderCompanies .map function. I keep getting "Cannot read property 'setState' of undefined" . This should be simple but I have not been able to do it
Make sure the function given to map is bound as well, or an arrow function:
{this.props.companies.map((item, i) => {
return (
<div>
<div
key={i}
onClick={() => {
this.setState({ currentCompany: item });
}}
>
{i}: {item.name}
</div>
<button>Delete Company</button>
</div>
);
})}
The function passed to this.props.companies.map isn’t an arrow function, so it creates a new this. Change it to an arrow function to preserve the this from outside of it.
this.props.companies.map( ( item, i ) => { ... } )
You’ve also named the argument to onClick item, but it’s actually the click event. You want the item already defined by the map function. Name the argument to onClick something else, or nothing, to avoid overwriting the item variable you actually want.
onClick={ () => { ... } }
I've been scratching my head for hours trying to figure out why do I get a syntax error when trying to iterate a multidimensional array :
const InputPanel = React.createClass({
render() {
const { board } = this.props;
return(
<br />
{board.map(rows => {
rows.map(cell => <div className="digit">1</div>);
})
}
);
}
});
CodePen:
http://codepen.io/anon/pen/vXgmrR
I tried to add\modify parenthesis types and nothing helps.
Here is the view i'm trying to produce:
</br>
<div className="digit">1</div>
<div className="digit">1</div>
<div className="digit">1</div>
</br>
<div className="digit">1</div>
<div className="digit">1</div>
<div className="digit">1</div>
</br>
<div className="digit">1</div>
<div className="digit">1</div>
<div className="digit">1</div>
There are a couple of problems with the code.
Your rows.map(...) statement isn't actually outputting anything. You need to return the result of rows.map to have it rendered.
You could do this:
{board.map(rows => {
return rows.map(cell => <div className="digit">1</div>);
})
}
or this:
{board.map(rows => rows.map(cell => <div className="digit">1</div>))}
It's not clear to me if this in the render method will actually reference the component. I usually use ES2015 classes or stateless functions to create my components, simply because the logic seems clearer to me.
So, your component could be rewritten:
class InputPanel extends React.Component {
render() {
const { board } = this.props;
return(
<br />
{board.map(rows =>
rows.map(cell => <div className="digit">1</div>)
)
}
);
}
}
or, even more simply:
const InputPanel = ({ board }) => (
<br />
{board.map(rows => rows.map(cell => <div className="digit">1</div>))}
);
Now, I could be wrong about this - like I said, I'm not that familiar with the React.createClass way of doing things.
React is not going to like that bare <br /> in your component. render methods need to return a single element, so you're going to need to wrap everything in your render method in a <div> or some other element.
And this final one is the source of your syntax error: without that wrapping element, Javascript (or more accurately whatever system you're using to interpret JSX code) sees something like this:
return (
{ /* some Javascript code here */ }
);
which is not valid Javascript - you can't just return a code block like that.
With an enclosing <div>, the code looks like this:
return (
<div>
{ /* some Javascript code here */ }
</div>
);
which is valid JSX code and your JSX preprocessor can parse it.
So, to wrap it all up, the simplest form of your component would look something like this:
const InputPanel = ({ board }) => (
<div>
{board.map(rows => rows.map(cell => <div className="digit">1</div>))}
</div>
);
As an aside, I'd recommend looking into eslint to lint your code & catch errors like this. I try to use it religiously and I like to think it has improved my code quality :-)
for react native had an issue where I was all ready doing a map iteration
but had one key that was an object i was doing something like:
{this.state.some_data.map(item => (
<View style={styles.row} key={item.product_id}>
<Text style={styles.header}>{item.title}</Text>
// BUT item.variations_json IS a multi dimential object ???
</View>
))}
The Solution for me was ..
render() {
//...
const someVariation = (variation, product_id) => {
var vdata = [];
Object.entries(variation.data).map(([key,v]) => {
vdata.push(
<View key={key}>
<Text >{v.sku}</Text>
<Text >{v.title}</Text>
<Text>{v.price}</Text>
</View>
);
});
return vdata;
};
//...
then Later
{this.state.some_data.map(item => (
<View style={styles.row} key={item.product_id}>
<Text style={styles.header}>{item.title}</Text>
<someVariation data={item.variations_json} id={item.product_id}></someVariation>
</View>
))}