I've looked at a bunch of questions here and read the docs over and over, however this just doesn't seem to want to work no matter what I do.
This is supposed to return one thing if X is true and return something else if it's not. It's inside a map function because I need this to be done for multiple things at once.
function ContentProcessing(props) {
return (
<div>
props.content.map(content => {
{content.type === "card" ? (
<Card title={content.title} />
) : (
<Content title={content.title} paragraph={content.guideline} />
)}
})
</div>
);
}
both <Card /> and <Content /> return one string
However I get the error
./src/App.js
Syntax error: /src/App.js: Unexpected token, expected , (79:13)
77 | <div>
78 | props.content.map(content => {
> 79 | {content.type === "card" ? (
| ^
80 | <Card title={content.title} />
81 | ) ? (
82 | <Content title={content.title} paragraph={content.guideline} />
I don't get why this isn't working.
Issues:
1- Use {} to put expressions inside jsx (to put map inside div).
2- you are using {} means block body of arrow function, so you need to use return inside the function body, otherwise by default map returns undefined.
3- You are using {} twice, so 2nd {} will be treated as object and content.type will be treated as key and that key is not valid, thats why you are getting error.
4- Forgot to define the key on elements.
Use this:
return (
<div>
{
props.content.map(content => content.type === "card" ? (
<Card title={content.title} />
) : (
<Content title={content.title} paragraph={content.guideline} />
)
)}
</div>
);
A couple of things are wrong I believe. You didn't add the curly braces in the first div. Inside the map you added two times the curly braces so you either remove one or add a return statement. You also added to "?" (the second one should be ":").
This should work:
function ContentProcessing(props) {
return (
<div>
{props.content.map(content =>
content.type === "card" ? <Card title={content.title} /> : <Content title={content.title} paragraph={content.guideline} />
)}
</div>
);
}
You can also add if else statements inside the map if you add braces:
function ContentProcessing(props) {
return (
<div>
{props.content.map((content) => {
if (content.type === "card") {
return (<Card title={content.title} />);
}
return (<Content title={content.title} paragraph={content.guideline} />);
})}
</div>
);
}
Your syntax for the ternary operator is wrong. You have condition ? a ? b. The correct syntax is condition ? a : b.
Try
function ContentProcessing(props) {
return (
<div>
{props.content.map(content =>
content.type === "card" ? (<Card title={content.title} />) :
(<Content title={content.title} paragraph={content.guideline} />)
)}
</div>
);
}
Multiple issues with the code.
return (
<div>
{props.content.map(content =>
content.type === "card" ? (
<Card title={content.title} />
) : (
<Content title={content.title} paragraph={content.guideline} />
)
)}
</div>
);
Extra brackets removed.
Conditional operator syntax was wrong.expression ? expression : expression
Related
for some reason, I get the "each child in a list should have unique key" error when returning the following code. I do not understand why this happens, as I specifically assign the key during mapping:
return (
<>
{sortfeedCards(feedCards)}
{loggedIn === true ? (feedCardsMod.map((card, index) => (
<>
<p>{index}</p>
<FeedCard key={index} cardData={card} loggedIn={loggedIn} />
</>
))) : ('')}
</>
)
And here's what the render looks like.. it seems to me that the index-variable does work:
Many Thanks in advance!
The key needs to be on the outermost element, so on the Fragment, not the FeedCard:
feedCardsMod.map((card, index) => (
<React.Fragment key={index}>
<p>{index}</p>
<FeedCard cardData={card} loggedIn={loggedIn} />
<React.Fragment/>
))
(The shorthand syntax <></> for fragments doesn't allow keys, so i switched to using React.Fragment explicitly)
Try this:
return (
<>
{sortfeedCards(feedCards)}
{loggedIn === true ? (feedCardsMod.map((card, index) => (
<div key={index}>
<p>{index}</p>
<FeedCard cardData={card} loggedIn={loggedIn} />
</div>
))) : ('')}
</>
)
Keys must be unique amongst the enclosing tags:
https://reactjs.org/docs/lists-and-keys.html
I have the following logic inside a react component where, I am rendering different component based on the boolean values. This peace of code is very difficult to understand. Are there anyways, I can simply that logic:
{isEnabled ? (
<>
{!loading ? (
<>
{items.length === 0 ? (
<>
<ComponentOne/>
<Container>
<img src={Image} alt="Image" />
</Container>
</>
) : (
<ComponentTwo/>
)}
</>
) : (
<div>
<LoadingComponent/>
</div>
)}
</>
) : (
<ComponentThree/>
)}
I'd probably split it up into seperate components and pass parameters down the component tree for example
{isEnabled ? <IsLoadingComponent loading={loading} items={items}> : <ComponentThree/>}
You might find it useful to split the component up into a "Loading" version and a "Loaded" version so you don't have to handle both states in the same component. Then the component basically just renders the "Loading" or "Loaded" version depending on the flag.
But even without that, you can at least make that easier to debug by using if/else if etc. and assigning to a temporary variable:
let comp;
if (isEnabled) {
if (loading) {
comp = <div>
<LoadingComponent/>
</div>;
} else if (items.length === 0) {
comp = <>
<ComponentOne/>
<Container>
<img src={Image} alt="Image" />
</Container>
</>;
} else {
comp = <ComponentTwo />;
}
} else {
comp = <ComponentThree />;
}
Then just
{comp}
where that nested conditional was.
I think you are making a simple thing very complicated. What we can do instead is that make use of "&&".
{ isEnabled && loading && <LoaderComponent /> }
{isEnabled && !items.length &&
<>
<ComponentOne/>
<Container>
<img src={Image} alt="Image" />
</Container>
</>
}
{isEnabled && items.length && <ComponentTwo/>}
{!isEnabled && <ComponentThree />}
Though I want to support the argument the others made (split into multiple components), you can already achieve a bit more readability by dropping unnecessary fragments (<></>) and/or parenthesis and by using "better"(opinion) indentation.
return (
isEnabled
? loading
? <div><LoadingComponent/></div>
: items.length === 0
? <> {/* this is the only place a fragment is actually needed */}
<ComponentOne/>
<Container>
<img src={Image} alt="Image"/>
</Container>
</>
: <ComponentTwo/>
: <ComponentThree/>
);
Alternatively, early returns do help a lot with readability. For example:
const SomeComponent = () => {
// ...snip...
if (!isEnabled) {
return <ComponentThree/>;
}
if (loading) {
return <div><LoadingComponent/></div>;
}
if (items.length > 0) {
return <ComponentThree/>;
}
return (
<>
<ComponentOne/>
<Container>
<img src={Image} alt="Image"/>
</Container>
</>
);
}
I am trying to render jsx using map and then using includes to display a text based on the value present in the list. It throws error saying "message": "Unexpected token. Did you mean {'}'}or}`. Can someone help me with this
The code that I have tried:
return (
<>
{list.length
?
list.map((item, idx) => {
return (
<span key={idx}>
{item}
</span>
)}
{list.includes("Test") && (
<span key="test">
Replacement
</span> )
}
)
: "-"}
</>
);
You are calling list.includes inside your map function after you closed the curly bracket. I think you wanted something like this:
return (
<>
{list.length
?
(<>
{list.map((item, idx) => {
return (
<span key={idx}>
{item}
</span>
)}
)}
{list.includes("Test") && (
<span key="test">
Replacement
</span> )
}
</>)
: "-"}
</>
);
If currentProfiles.length > 0, I'd like to map over an array named profiles and render a profile component for each profile, and render a pagination component below the profiles. I tried this with a single ternary operator, but this results in only the pagination component being rendered.
{currentProfiles.length > 0 ? (
(currentProfiles.map(profile => (
<ProfileItem key={profile._id} profile={profile} />
)),
(
<Pagination
profilesPerPage={profilesPerPage}
totalProfiles={profiles.length}
/>
))
) : (
<Spinner />
)}
If I use two separate ternary operators, I get the list of profiles and pagination as expected, but can I do both things with a single conditional operator?
Your code just needs some restructuring. If you wrap the mapped profiles and pagination components in a parent fragment or other element, it's easy. Note, too, that the first example below still retains the ternary, as requested.
return (
<div className="App">
{currentProfiles.length ? (
<>
{currentProfiles.map(p => (
<Profile {...p} />
))}
<Pagination profilesPerPage={2} totalProfiles={totalProfiles} />
</>
) : (
<p>Loading...</p>
)}
</div>
);
However, you have a few options aside from wrapping them in a non-rendered Fragment or its shorthand derivative. You could also use an actual element, such as a div. Or even omit the parent entirely and place your logic within an array, as in:
<div className="App">
{currentProfiles.length ? [
currentProfiles.map(p => (
<Profile {...p} />
)),
<Pagination profilesPerPage={2} totalProfiles={totalProfiles} />
] : <p>Loading...</p>}
</div>
Always remember that, unless you utilize the second approach, you'll need to ensure siblings share a common parent.
Working example.
You can use an array or a fragment https://reactjs.org/docs/fragments.html
{currentProfiles.length > 0 ? (
<>
currentProfiles.map(profile => (
<ProfileItem key={profile._id} profile={profile} />
)
<Pagination
profilesPerPage={profilesPerPage}
totalProfiles={profiles.length}
/>
</>
) : (
<Spinner />
)}
I'm trying to render multiple child components depending on state however I'm only able to return one child component (SyntaxError: Adjacent JSX elements must be wrapped in an enclosing tag)
Each child component passes the same props, how could this code be kept DRY?
Works
export default ({changeState, myState, handleClick}) => (
<Navigation>
<span>Navigation</span>
<button onClick={() => changeState()}>Navigation</button>
{ myState ?
<NavigationItem handleClick={handleClick} title={'#Link-1'} />
: null
}
</Navigation>
)
Don't
export default ({changeState, myState, handleClick}) => (
<Navigation>
<h1>Navigation</h1>
<button onClick={() => changeState()}>Navigation</button>
{ myState ?
<NavigationItem handleClick={handleClick} title={'#Link-1'} />
<NavigationItem handleClick={handleClick} title={'#Link-2'} />
<NavigationItem handleClick={handleClick} title={'#Link-3'} />
: null
}
</Navigation>
)
Directly we can't return more than one elements.
Possible Solutions:
1- Either you need to wrap all the elements in a div or any other wrapper element.
2- We can return an array of multiple elements also, So put all the items in an array, and return the array.
Like this:
{myState ?
[
<NavigationItem handleClick={handleClick} title={'#Link-1'} />,
<NavigationItem handleClick={handleClick} title={'#Link-2'} />,
<NavigationItem handleClick={handleClick} title={'#Link-3'} />
]
: null
}
Check this example:
let b = true ? [1,2,3,4]: null;
console.log('b = ', b);
This will throw error:
let b = true? 1 2 3 4: null;
console.log('b = ', b);
You can also use <Fragment> from ReactJS: https://reactjs.org/docs/fragments.html
The problem about wrapping all the elements with a <div>, is that you are adding more elements to the DOM, and sometimes it's impossible (for example, when you are rendering a <td> or <tr> inside a <table>. So, here is where <Fragment> comes to help us.
Just wrap all those elements in a <Fragment> and it'll be enough.
Meaning:
{ myState &&
<Fragment>
<NavigationItem handleClick={handleClick} title={'#Link-1'} />
<NavigationItem handleClick={handleClick} title={'#Link-2'} />
<NavigationItem handleClick={handleClick} title={'#Link-3'} />
</Fragment>
}
Anyways, this another "Conditional Rendering" approach is better in "code readability" sense: https://medium.com/#BrodaNoel/conditional-rendering-in-react-and-jsx-the-solution-7c80beba1e36
It basically proposes the use of a <Conditional> element, like:
<Conditional if={myState}>
<NavigationItem handleClick={handleClick} title={'#Link-1'} />,
<NavigationItem handleClick={handleClick} title={'#Link-2'} />,
<NavigationItem handleClick={handleClick} title={'#Link-3'} />
</Conditional>
^ This looks better for my eyes :D