I started my learning path few months ago (html, css, js) and I have a question for an issue that I have with react (just started learning it).
I have an error that says : data.map is not a function
I want to loop trough my array of objects with map, and dispatch the props (title, answer) to the child for each loop, to make a list of different FaqComponent having each the {title and answer}
const data = useSelector(state => ({
...state.homePage.list
}))
console.log(data);
return (
<div>
{data.map((title, answer) => (
<FaqComponent
title={title}
answer={answer}
/>
))}
</div>
);
}
export default ...;
Thanks for your replies
You're using an object {} instead of an array [] syntax.
Try with:
const data = useSelector(state => ([
...state.homePage.list
]));
You should declare "data"s type, if it is an array so your function should be like :
const data = useSelector(state => ([
...state.homePage.list
]))
console.log(data);
return (
<div>
{(data && data.length > 0) ? data.map((item, i) => (
<FaqComponent
title={item.title}
answer={item.answer}
key={i}
/>))
: <div>No Result!...</div>}
</div>
);
}
export default ...;
Related
I have the following functional component and de-structuring the parameter props:
const MyTimes = ({ myWindowGroup, name, fieldArrayName }) => (
<FieldArray
name={name}
render={(arrayHelpers) => (
<React.Fragment>
{myWindowGroup.fieldArrayName.map((myTime, index) => (
and I am calling the component with the following props:
<MyTimes
myWindowGroup={myWindowGroup}
fieldArrayName={"myTimes"}
name={`myWindowGroups.${index}.myTimes`}
/>
My question is as I am new to React and that is, how can I pass/use the fieldArrayName={"myTimes"} string value of myTimes into the MyTime component above so that I can replace the value of fieldArrayName.map to be myTimes.map ?
I've tried it the way it is and not working.
Use dynamic keys. See Bracket Notation.
myWindowGroup[fieldArrayName].map(....
const myWindowGroup = {
myTimes: ['This is the value array you want'],
foo: [],
};
console.log(myWindowGroup['myTimes']);
console.log(myWindowGroup['foo']);
You can just do
{myWindowGroup[fieldArrayName].map((myTime, index) => (
As I understand your question correctly, you can achieve desired output by following
const MyTimes = ({ myWindowGroup, name, fieldArrayName }) => (
<FieldArray
name={name}
render={(arrayHelpers) => (
<React.Fragment>
{myWindowGroup[fieldArrayName].map((myTime, index) => (
// your logic here
))}
I get an array and want objects with different TPAs (Item.Type) add to different components. But in the end I only get the last. How to do what would both ITEM be saved in the component and did not flip each other?
{
list.map((item) => (
<div>{item.type == 1 ? <DetailedOne item={item} /> : ""}</div>
));
}
{
list.map((item) => (
<div>{item.type == 2 ? <DetailedTwo item={item} /> : ""}</div>
));
}
I think it as simple as using find to find both items from the list and passing those to their components:
const [item1, item2] = useMemo(() => {
const item1 = list.find((item) => item.type === 1)
const item2 = list.find((item) => item.type === 2)
return [item1, item2]
}, [list])
// JSX
<DetailedOne item={item1} />
<DetailedTwo item={item2} />
You can use concat() to combine the results from both map() calls.
Furthermore, I would recommend using .filter() because you are now creating empty <div>s that look like nothing but pollution to me.
Code:
{
list.filter(item.type == 1).map((item) => (
<div><DetailedOne item={item}</div>
)).concat(
list.filter(item.type == 2).map((item) => (
<div><DetailedTwo item={item}</div>
))
);
}
I need to set ref to each project inside map function. I'm forwardingRef from child to my parent and currently I'm getting only single Project. I need to set refs to array list and then work with it. I tried something like this:
const projectSectionItem = useRef([])
ref={projectSectionItem => projectSectionItem[index] = projectSectionItem}
PARENT:
const projectSectionItem = useRef<HTMLDivElement>(null)
<StyledSection ref={projectSection}>
{data.map((i, index) => {
return i.showOnHP === 1 ?
<Element name={index.toString()} key={index}>
<Project
url={`${URL}${i.button_image.image}`}
client={i.client_name}
project={i.project.en}
btn_color={"#000"}
btn_text={i.button_text}
href={`/cases/${i.slug}`}
ref={projectSectionItem}
>
</Project>
</Element>
: null
})}
CHILD:
export const Project = React.forwardRef<HTMLDivElement, ProjectProps>((props, ref) => {
return (
<StyledProject className={props.className} ref={ref}>
...
</StyledProject>
)
})
Since you should not use hooks (useRef) in a loop or conditionally, you can just use createRef like this:
const pressureRefs = data.filter(item => item.showOnHP).map(() => React.createRef<HTMLDivElement>())
<Project ... ref={refs[i]} />
I am pretty much new to hooks so have a question here:
I have in React component function like
const getSection = assignmentSectionId => {
const findSection = sections.find(
section => section.sectionRefId === assignmentSectionId,
);
return findSection ? findSection.name : '';
};
and now I got suggestion to use useMemo on that function. Currently I am using like:
return (
<List
role="list"
aria-label={ariaLabel}
>
{assignments.map(assignment => {
const sectionName = getSection(assignment.sectionId);
return (
<Card
name={sectionName}
/>
);
})}
</List>
);
};
What is the best(optimal) way to use useMemo here if it is possible?
You could use the Array#map inside the useMemo .Its only re-render the list After assignments value change
const memoList = React.useMemo(()=> assignments.map(assignment => {
const sectionName = getSection(assignment.sectionId);
return (<Card name={sectionName}/>)
}),[assignments])
return (
<List role="list" aria-label={ariaLabel}>{memoList}</List>
);
};
I am converting class based components to react hooks. I got confused on using the ref parts. Because, the way I am using it complains me that The "innerRef" API has been removed in styled-components v4 in favor of React 16 ref forwarding, use "ref" instead like a typical component..
How do i make it work when using hooks?
const Tabs = ({activeTab, children}) => {
const [tabsElements, setTabsElements] = useState([])
return (
<TabsContext.TabProvider activeTab={activeTab}>
<TabsContext.TabConsumer>
{value => (
<ReactTabs>
<TabsContainer>
<ListTabs>
{value.context.tabs.map(tab => (
<TabTitleItem
key={tab.id}
onClick={value.context.onClick(tab)}
id={tab.id}
innerRef={tabElement => {
if (!tabsElements[tab.id]) {
setTabsElements(tabElements => ({
...tabElements,
[tab.id]: tabElement,
}))
}
}}
isActiveTab={value.context.activeTab.id === tab.id}
>
<TabAnchorItem>{tab.title}</TabAnchorItem>
</TabTitleItem>
))}
</ListTabs>
<ActiveTabBorder
activeTabElement={tabsElements[value.context.activeTab.id]}
/>
</TabsContainer>
{children}
</ReactTabs>
)}
</TabsContext.TabConsumer>
</TabsContext.TabProvider>
)
}
Here is the demo
https://codesandbox.io/s/z3moq8662p
First of all you cannot update state within the ref callback method. Secondly you simply need to pass ref instead of innerRef to the TabTitleItem component since it internally handles ref using forwardRef
const Tabs = ({ activeTab, children }) => {
const [tabsElements, setTabsElements] = useState([]);
const tabElements = useRef({});
return (
<TabsContext.TabProvider activeTab={activeTab}>
<TabsContext.TabConsumer>
{value => (
<ReactTabs>
<TabsContainer>
<ListTabs>
{console.log("value", value.context)}
{value.context.tabs.map(tab => (
<TabTitleItem
key={tab.id}
onClick={value.context.onClick(tab)}
id={tab.id}
ref={tabElement => {
tabElements.current[tab.id] = tabElement;
}}
isActiveTab={value.context.activeTab.id === tab.id}
>
<TabAnchorItem>{tab.title}</TabAnchorItem>
</TabTitleItem>
))}
</ListTabs>
<ActiveTabBorder
activeTabElement={tabsElements[value.context.activeTab.id]}
/>
</TabsContainer>
{children}
</ReactTabs>
)}
</TabsContext.TabConsumer>
</TabsContext.TabProvider>
);
};
Working demo