I would like to know how can i destruct object within .map function using javascript, i have react js component and within return method i have the code below:
return (
<>
{setItems.map(setItem => (
const { childContentfulPartFeatureSetLearnMoreOptionalTextTextNode: learnNode} = setItem
....
</>
and i have the next error: Parsing error: Unexpected token ... = setItem, i thought what it is
EsLinterror and used // eslint-disable-next-line to disable it, but it didn't work.
UPD full return code:
return (
<div className={generalServiceItemClassName} key={guuid()}>
{setItems.map(setItem => (
const { childContentfulPartFeatureSetLearnMoreOptionalTextTextNode: learnNode} = setItem
<div
key={guuid()}
className={cx(columnSizeClass, "service-items__item")}
data-test="service-items"
>
{setItem.learnMore ? (
<LearnMore
className="service-items__item-learn-more-container"
learnMoreLink={setItem.learnMore}
text={}
textClassName="service-items__item-texts-learn-more"
learnMoreText={learnNode ? learnNode.setItem : null}
>
{renderItem(setItem)}
</LearnMore>
) : (
renderItem(setItem)
)}
</div>
))}
</div>
)
You can't have a const declaration within an expression, and when you use the concise form of an arrow function (=> without a { after it), the body is an expression.
You can destructure in the parameter list, though. For instance:
{setItems.map(({childContentfulPartFeatureSetLearnMoreOptionalTextTextNode: learnNode}) => (
// ...use `learnNode` here...
In context:
return (
<div className={generalServiceItemClassName} key={guuid()}>
{setItems.map(({childContentfulPartFeatureSetLearnMoreOptionalTextTextNode: learnNode}) => (
<div
key={guuid()}
className={cx(columnSizeClass, "service-items__item")}
data-test="service-items"
>
{setItem.learnMore ? (
<LearnMore
className="service-items__item-learn-more-container"
learnMoreLink={setItem.learnMore}
text={}
textClassName="service-items__item-texts-learn-more"
learnMoreText={learnNode ? learnNode.setItem : null}
>
{renderItem(setItem)}
</LearnMore>
) : (
renderItem(setItem)
)
}
</div>
))}
</div>
);
Try something like this. (destructure and renaming)
const setItems = [{ abc: 5 }];
return (
<>
{setItems.map((setItem) => {
const { abc: xyz } = setItem;
return <div>{xyz}</div>;
})}
</>
);
// Alternate way, simplified.
return (
<>
{setItems.map(({ abc: xyz }) => (
<div>{xyz}</div>
))}
</>
);
Related
I have followed this tutorial (https://www.freecodecamp.org/news/pass-data-between-components-in-react/) to the best of my ability but I am still having trouble
I am getting the following error:
Uncaught TypeError: childToParent is not a function"
Here is the parent function:
function App() {
const childToParent =(value) => {console.log(value)}
...
return (
...
<SelectHours value={state.selectedHour} childToParent={childToParent}></SelectHours>
...
)
and the child function:
export default function SelectHours(selectedHours, childToParent) {
....
return (
<Select
labelId="select-demo"
id='select-demo'
defaultValue=""
//onChange={event => handleChange(event.target.value, true)}
value={workHours[0] ? workHours[0] : ""}
>
{
workHours.map((value, index) => {
return (
<MenuItem
value={value ? value : ""}
key={index}
onClick={() => childToParent(value)}
>
{value}
</MenuItem>
)
})
}
</Select>
)
....
}
You need to add your curly braces so react can tell its a prop.
export default function SelectHours({selectedHours, childToParent}) {
....
return (
<Select
labelId="select-demo"
id='select-demo'
defaultValue=""
//onChange={event => handleChange(event.target.value, true)}
value={workHours[0] ? workHours[0] : ""}
>
{
workHours.map((value, index) => {
return (
<MenuItem
value={value ? value : ""}
key={index}
onClick={() => childToParent(value)}
>
{value}
</MenuItem>
)
})
}
</Select>
)
....
}
must destruct props like this.
export default function SelectHours({selectedHours, childToParent})
or use props like this
export default function SelectHours(props)
...
onClick={() => props.childToParent(value)}
read about object destructuring in this article
https://dmitripavlutin.com/javascript-object-destructuring/
You need to have a handler for ChildToParent inside
function App() {
...
const childToParent =(value) => {console.log(value)}
return (
...
<SelectHours value={state.selectedHour} childToParent={childToParent}></SelectHours>
...
)
the App component
am trying to show Noteitem component which is returned inside a map function.
{notes.map((note) => {
return (
<Noteitem key={note._id} updateNote={updateNote} showAlert={props.showAlert} note={note} />
);
})}
notes should be an array for map function to work. You can check it in following way if notes is not null and is an array using notes.length and apply map function
{notes && notes.length && notes.map((note) => {
return (
<Noteitem key={note._id} updateNote={updateNote} showAlert={props.showAlert} note={note} />
);
})}
You can put if/else statement inside JSX to check the variable whether is exist or not
return (
<>
{
notes.length
? 'fallback'
: notes.map(note => <Noteitem key={note._id} updateNote={updateNote} showAlert={props.showAlert} note={note} />)
}
</>
)
IIFE
{(() => {
if ("check note") {
// fallback
}
return notes.map((note: NoteProps) => (
<Noteitem key={note._id} updateNote={updateNote} showAlert={props.showAlert} note={note} />
));
})()}
I'm currently rendering two different components based on the value of shouldRenderPlanA - however, despite different components being rendered (depending on the value) - I pass both the same props. How can I condense this to reduce repeated code?
return (
<>
{options.map(option)}
<StyledRow>
{variousOptions.map((opt) => (
shouldRenderPlanA ? (
<StyledLabelOptionOne
variousProps={variousProps}
variousProps={variousProps}
variousProps={variousProps}
/>
) : (
<StyledLabelOptionTwo
variousProps={variousProps}
variousProps={variousProps}
variousProps={variousProps}
/>
)
))}
</StyledRow>
</>
);
To pass same Props to multiple React component or to pass multiple Props to a React component, you can use Object unpacking/destruction within components.
function Component() {
const propPack = {
variousProps1: variousProps1,
variousProps2: variousProps2,
variousProps3: variousProps3,
};
return (
<>
{options.map(option)}
<StyledRow>
{variousOptions.map((opt) => (
shouldRenderPlanA
? <StyledLabelOptionOne {...propPack} />
: <StyledLabelOptionTwo {...propPack} />
))}
</StyledRow>
</>
);
}
This is commonly used to pass all the parent props down to children
function Component(props) {
return (
condition
? <StyledLabelOptionOne {...props} />
: <StyledLabelOptionTwo {...props} />
)
}
You can also conditionally pick the component for rendering (but this IMHO is less readable)
function Component() {
const PickedComponent = shouldRenderPlanA ? StyledLabelOptionOne : StyledLabelOptionTwo;
return (
<>
{options.map(option)}
<StyledRow>
{variousOptions.map((opt) => (
<PickedComponent
variousProps1={variousProps1}
variousProps2={variousProps2}
variousProps3={variousProps3}
/>
))}
</StyledRow>
</>
);
}
For conditions/props derived from within .map() simply move the code within the map callback
function Component() {
return (
<>
{options.map(option)}
<StyledRow>
{variousOptions.map((opt) => {
const propPack = {
variousProps1: variousProps1,
variousProps2: opt.value,
};
const PickedComponent = opt.condition ? StyledLabelOptionOne : StyledLabelOptionTwo;
return (
shouldRenderPlanA
? <StyledLabelOptionOne {...propPack} />
: <StyledLabelOptionTwo {...propPack} />
)
})}
</StyledRow>
</>
);
}
Note how arrow function within map has becomed an arrow function with a complete block. From (opt) => (first_instruction) to (opt) => { first_instruction; return (second_instruction); }. This allows us to add code before rendering at each map() cycle.
You could assign both options to a variable which contains a union of both component types.
Combining and then spreading the props from an object may also be beneficial, depending on where those props come from. If they are taken from opt inside the map then this second step is probably not required:
const LabelComponent = shouldRenderPlanA ? StyledLabelOptionOne : StyledLabelOptionTwo;
return (
<>
{options.map(option)}
<StyledRow>
{variousOptions.map((opt) => (
<LabelComponent
prop1={opt.prop1}
prop2={opt.prop2}
/>
))}
</StyledRow>
</>
);
You could use the React Context API. This would enable you to share the props across multiple children without passing it to each one of them explicitly.
I couldn't understand why...here is the GitHub repository: https://github.com/Dronrom/React-test
That’s because you initialized peopleList as null in your component. So map works only on arrays so you need to check peopleList whether its really an array before doing map on it so
Change
renderItems(arr) {
return arr.map(({id, name}) => {
return (
<li className="list-group-item"
key={id}
onClick={() => this.props.onItemSelected(id)}>
{name}
</li>
);
});
}
To
renderItems(arr) {
if(arr){
return arr.map(({id, name}) => {
return (
<li className="list-group-item"
key={id}
onClick={() => this.props.onItemSelected(id)}>
{name}
</li>
);
});
}
}
I think your issue may be that react renders once before componentDidMount(). This is an issue because your calling map on arr which is null. const { peopleList } = this.state; you set people list to your current state which you set as default to be null, state = {peopleList: null}; then you later call this.renderItems(peopleList); which people list is still null at this moment so you are getting the Cannot read property 'map' of null error.
I belive something like componentWillMount is what you need instead. I recommend looking at this post which has a similar issue of react life cycle methods. React render() is being called before componentDidMount()
the answer is very simple: the type of the input isn't array type, it might be null or undefined. so that it doesn't have .map function.
How to fix:
Make sure your input must be array type before call renderItems().
render(){
const { peopleList } = this.state;
const items = (peopleList && peopleList.length) ? this.renderItems(peopleList) : null;
return(
<ul className="item-list list-group">
{items}
</ul>
);
}
Or:
Make sure your input must be array type before do mapping:
renderItems(arr) {
return !arr ? null : arr.map(({id, name}) => {
return (
<li className="list-group-item"
key={id}
onClick={() => this.props.onItemSelected(id)}>
{name}
</li>
);
});
{product.size?.map(c=>(
<FilterSizeOption key={c}>{c}</FilterSizeOption>
))}
Wrapping the return statement with a if statement worked for me
So changed
return (
<div>
<Navbar />
{countries.map((country, i) => {
return (
<div>
<span key={`${country.name.common}${i}`}>
{country.name.common}
</span>
</div>
);
})}
</div>
);
to this
if (countries) {
return (
<div>
<Navbar />
{countries.map((country, i) => {
return (
<div>
<span key={`${country.name.common}${i}`}>
{country.name.common}
</span>
</div>
);
})}
</div>
);
}
This is my following code:-
if(this.props.buttons && this.props.buttons.tabs && this.props.buttons.tabs.length) {
this.props.buttons.tabs.map((button) => {
return (
<TabsPanel label={button.labelKey} />
button.subtabs.map((subtab) => {
return(
<Tabs>
<TabsPanel label={subtab.labelKey}></TabsPanel>
</Tabs>
)
})
)
});
}
While running this following code it's always giving Syntax Error.
Here's my following JSON which I am getting
"tabs" : [
{
"labelKey" : "label1",
"subtabs" : [
{
"form" : {
"labelKey" : "subtab1"
}
},
{
"form" : {
"labelKey" : "subtab2"
}
}
]
},
{
"labelKey" : "label2"
}
]
Any leads would be helpful. I am stuck at a dead end right now.
Thanks!
The question is not very clear. But here are a few scenarios that I think could be intended.
TabsPanel component accepts Tabs as children:
Answer by Prabin is as correct as it gets. (Except for missing key attributes in TabsPanel and Tabs components)
TabsPanel component and Tabs list go side by side:
Note: A valid component is either one single root, or it is a list of other valid components.
So either this is correct.
this.props.buttons.tabs.map((button, index) => {
return (
<div key={index}>
<TabsPanel label={button.labelKey} />
{button.subtabs.map(subtab => {
return (
<Tabs key={subtab.labelKey}>
<TabsPanel label={subtab.labelKey} />
</Tabs>
)
})}
</div>
)
})
Or this is correct.
this.props.buttons.tabs.map((button, index) => {
return [
<TabsPanel label={button.labelKey} key={index} />,
{
...button.subtabs.map(subtab => {
return (
<Tabs key={subtab.labelkey}>
<TabsPanel label={subtab.labelKey} />
</Tabs>
)
})
}
]
})
Also, note the key attribute in Tabs and TabsPanel components. That is important and I leave it up to you to find it's importance.
return (
<div>
{this.props.buttons && this.props.buttons.tabs && this.props.buttons.tabs.length &&
this.props.buttons.tabs.map(button => {
return (
<TabsPanel label={button.labelKey}>
{button.subtabs.map(subtab => {
return (
<Tabs>
<TabsPanel label={subtab.labelKey} />
</Tabs>
);
})}
</TabsPanel>
);
})}
</div>
);
Try this should solve your problem