Pass Component from JS Object as props in React - javascript

I'm reading from a JS object (from JSX) and trying to pass value of a component but it's rendered as string.
I tried placing components (in icon key of data see below) in {} but that doesn't help as data gives an error.
Here's the simplified version of the files.
data.js as below:
const data = [
{
title: "some title",
desc: "some desc",
},
[
{
icon: "<TwitterIcon />",
title: "title 1",
desc: "desc 1",
},
{
icon: "<FacebookIcon />",
title: "title 2",
desc: "desc 2",
},
],
]
export { data }
index.js that reads data object and passes as props to AnotherComponent:
import { data } from "../path/to/data"
import AnotherComponent from "../path/to/AnotherComponent"
const Homepage = () => {
return (
<AnotherComponent {...data} />
)
}
AnotherComponent.jsx as below:
import {TwitterIcon, FacebookIcon} from "../path/to/CustomIcons"
const AnotherComponent = ({ ...data}) => {
return (
{data[1].map(item => (
<div>{item.icon}</div> // this prints string as opposed to rendering the component
<div>{item.title}</div>
<div>{item.desc}</div>
))}
)
}
index.js returns:
<div><TwitterIcon /></div>
<div>title 1</div>
<div>desc 1</div>
<div><FacebookIcon /></div>
<div>title 2</div>
<div>desc 2</div>

In the object you are defining as:
{
icon: "<TwitterIcon />",
title: "title 1",
desc: "desc 1",
}
Don't use "<TwitterIcon />" It will always return a string, instead use TwitterIcon:
{
icon: TwitterIcon,
title: "title 1",
desc: "desc 1",
}
And finally, call it where you need it, in this way:
const AnotherComponent = ({ ...data}) => {
return (
{data[1].map(item => (
<div><item.icon /></div> // HERE: check I'm calling item.icon as React Component
<div>{item.title}</div>
<div>{item.desc}</div>
))}
)
}
In this way you are passing the icon to anywhere you want and not just passing a string. So, you can call it as a Component when you need it to render. I do it a lot in my work.

I think you should pass directly the icon component in the object, like this:
const data = [
{
title: "some title",
desc: "some desc",
},
[
{
icon: <TwitterIcon />,
title: "title 1",
desc: "desc 1",
} ...
Then in index.js you can do (it is more clear to pass down props like this):
const Homepage = () => {
return (
<AnotherComponent data={data} />
)
}
In AnotherComponent.jsx now you can do:
const AnotherComponent = ({data}) => {
return (
{data[1].map(item => (
<div>{item.icon}</div>
<div>{item.title}</div>
<div>{item.desc}</div>
))}
)
}

Related

Pushing array with useState()

Everyone! i just have this kind of problem that i can`t fix.
this is my App.js
import { useState } from "react"
import Header from "./components/header"
import FeedbackList from "./components/FeedbackList"
import FeedbackData from "./data/FeedbackData"
function App() {
const [feedback, setFeedback] = useState(FeedbackData)
return (
<>
<Header />
<div className="container">
<FeedbackList feedback={feedback} />
</div>
</>
) }
export default App
and this is my second js file that i want to use "feedback" prop like array
import FeedbackItem from "./FeedbackItem"
import FeedbackData from "../data/FeedbackData"
function FeedbackList(feedback) {
return (
<div>
{feedback.map((item)=>(
<FeedbackItem key={item.id} item={item}/>
))}
</div>
)
}
i cant use feedback.map function in this case because feedback is not like array (sorry for my bad english) i solve this problem without using hooks but i want to know what i can do in this case,sorry if im writing something wrong im just new in React and trying to learn.
In Javascript there are object and array. Both can be mapped.
For Array.
const arr = [
{ name: "name 1", id: "01" },
{ name: "name 2", id: "02" },
{ name: "name 3", id: "03" },
];
arr.map(item=> (<div key={item.id}>{item.name}</div>))
For Object.
const obj = {
"item01": { name: "name 1" },
"item02": { name: "name 1" },
"item03": { name: "name 1" },
};
Object.keys(obj).map((key)=> <div key={key}>{obj[key].name}</div>)
Check your type, console.log(typeof FeedbackData).
If it is not type error. Instead of
const [feedback, setFeedback] = useState(FeedbackData)
Try this.
const [feedback,setFeedback] = useState([])
useEffect(()=> setFeedback(FeedbackData),[])
what you want is to destructure the prop you need from the 'props' object.
function Component1() {
const [val, setVal] = useState([]);
return <Component2 val={val} />
}
function Component2({ val }) {
return val.map...
}
this is equivalent to doing:
function Component2(props) {
return props.val.map...
}
this is because props is an object, and so you need to get the right key from the object based on the prop name, either by destructuring or accessing it via props.propName

map function not showing elements on screen

i have this part of code the map function did not show any element of the array, if i console.log the variable it shows me the elements but for some reasons i can't show the elements on the screen.
Code
function Solution({list}){
const data = list
console.log(data);
return(
<div>
{
data?.map((item) => {
return (
<div>
<p> {item.title} </p>
</div>
)
})
}
</div>
)
}
export default Solution;
const list = [
{
title: "Home"
},
{
title: "Service",
subItem: ["Clean", "Cook"]
},
{
title: "Kitchen",
subItem: ["Wash", "Dish"]
},
];
Solution({list})
Please, just pass "list" link this.
<Solution list={list}/>
Hope will help you, Thanks)
Check this out
import React from 'react';
function Solution({list}){
const data = list
console.log(list);
return(
<div>
{
data?.map((item) => {
return (
<div key={item.id}>
<p> {item.title} </p>
</div>
)
})
}
</div>
)
}
export function App(props) {
const list = [
{
id:1,
title: "Home"
},
{
id:2,
title: "Service",
subItem: ["Clean", "Cook"]
},
{
id:3,
title: "Kitchen",
subItem: ["Wash", "Dish"]
},
];
return (
<div className='App'>
<Solution list={list} />
</div>
);
}
// Log to console
console.log('Hello console')
Have a unique key prop for each element when you map an array and send list array as props to your Solution component

React .map function not passing data to useState

Why is my setSelected useState not accepting the data from the .map function? I have the following react js code:
const [ selected, setSelected ] = useState(null)
const sectionItems = [
{ id: "1", title: "title1", description: "description1" },
{ id: "2", title: "title2", description: "description2" },
{ id: "3", title: "title3", description: "description3" },
]
I am mapping through the sectionItems and rendering a modal, based on if selected has an item or not:
{sectionItems.map((section, index) => {
return (
<div key={section.id} className="processSection1" onClick={setSelected(section) >
<div className="processTitle" >{section.title}</div>
</div>
)
})}
{selected ? <Modal title={selected.title} description={selected.description} /> : " "}
Problem: Why cant I pass the data into setSelected? Or the more precise question is, how can I render the modal with each sectionItem?
Also am getting this error: Too many re-renders. React limits the number of renders to
prevent an infinite loop.
you have to use onClick like this
onClick={()=>setSelected(section)}
If you want to add a value to a function you should use an inline function inside the onClick. Right now you are triggering the function for each rendering at render time.
Change:
onClick={setSelected(section)}
to:
onClick={() => setSelected(section)}

Struggling in construction the tree hierarchy in react

I wanted to use tree view but I am struggling in construction the tree (hierarchical view of information) in react.
same as https://www.w3schools.com/howto/howto_js_treeview.asp
What I am trying CodeSandBox - https://codesandbox.io/s/unruffled-babbage-9knrz?file=/index.js
JSON - (this is not fixed can be any format)
const data = [
{
title: "Node 1",
childNodes: [
{ title: "Childnode 1.1" },
{
title: "Childnode 1.2",
childNodes: [
{
title: "Childnode 1.2.1",
childNodes: [{ title: "Childnode 1.2.1.1" }]
},
{ title: "Childnode 1.2.2" }
]
}
]
}
];
I have toggle function which expand and vice versa the tree node.
I am struggling in construction the tree in react.
Please guide me.
The first of all you don't need use <Tree/> as the recursive component, instead of it use <Node/>
The second thing in React you don't need to use the querySelector and classList for changing state of a component.
I've implemented my idea in code here
const Tree = () => {
return (
<ul>
{data.map(({ title, childNodes }) => (
<Node key={title} title={title} childNodes={childNodes} />
))}
</ul>
);
};
class Node extends React.Component {
state = {
isOpen: false
};
toggle = () => {
this.setState({
isOpen: !this.state.isOpen
});
};
render() {
const { title, childNodes } = this.props;
const { isOpen } = this.state;
return (
<li>
<span className="caret" onClick={this.toggle}>
{title}
</span>
{childNodes && isOpen && (
<ul>
{childNodes.map(({ title, childNodes }) => (
<Node key={title} title={title} childNodes={childNodes} />
))}
</ul>
)}
</li>
);
}
}
export default Tree

React - how to create a dynamic (using router) details pages

This is my data (in a seperate JS file):
const someData= [
{
id: 1,
title: "Article 1",
desc: "Some description lorem ipsum",
},
{
id: 2,
title: "Article 2",
desc: "Some description lorem ipsum",
},
{
id: 3,
title: "Article 3",
desc: "Some description lorem ipsum",
}
]
export default someData;
Now I'm mapping the data like this:
- Articles.js file
const articleItems = this.state.someData.map(item =>
<ArticleItem key={item.id} item={item}
/>)
return(
<div>{articleItems}</div>
)
And listing all articles with only the article title displayed in ArticleItem component.
- articleItem.js file
return(
<h1>{props.item.title}</h1>
)
How can I create so you can click on an article title in the list, which would then go to that specific article (url should be /article/id) and display all data for that specific article?
Use React Routers Version 4 to achiever this.
Article.js file-
const articleItems = this.state.someData.map(item =>
<Route key={item.id} path=`/${item.title}/${item.id}` render={
<ArticleItem
{...props}
item={item}
/>
} />
/>)
return(
<div>{articleItems}</div>
)
In the file where you are rendering the Links render like this.
render() {
return(
<Link to=`/${item.title}/${item.id}`>{item.title}</Link>
);
}
Don't forget to import Route and Link.
Hope this helps.

Categories

Resources