How to get JSX in an object from a function finding data (JSX) through another file? - javascript

I want to get JSX in an object (foundCategory) from another file categoriesDetails, by using the find funtion through checking the item.title. Below is my code
Here How I m retrieving and want to send data as props to a component (CategoryDetails).
import type { NextPage } from 'next';
import CategoryDetails from '../components/CategoryDetails.jsx'
import {categoryDetails} from '../utils/categoriesDetails'
const Home: NextPage = () => {
let foundCategory = null;
foundCategory = categoryDetails.find(function(item){
return item.title === 'Bus Plugs'
})
console.log(foundCategory)
return (
<>
<Header />
{foundCategory ? <CategoryDetails
oDetails={foundCategory.details}
sTitle={foundCategory.title}
/> : ''
}
<FooterBar/>
</>
)
}
export default Home
and Here is my categoriesDetails.js from which I m exporting categories data (Simplified)
export const categoryDetails = [
{
title: 'Bus Plugs',
details: (
<div>
<ul> </ul>
<img src={`${categoryImagesDir}bus-plugs-large.jpg`} />
</div>
)
},
{
title: 'Fuse',
details: (
<div>
<ul> </ul>
<img src={`${categoryImagesDir}fuse-large.jpg`} />
</div>
)
}
But when I console to check, I get the following result instead the actual JSX in foundCategory.details. which I want to use in child component (CategoryDetails).
{
title: 'Bus Plugs',
details: {
'$$typeof': Symbol(react.element),
type: 'div',
key: null,
ref: null,
props: { children: [Array] },
_owner: null,
_store: {}
}
}
Looking forward,
thanks

In your Home component, you have this code:
foundCategory = categoryDetails.find(function(item){
return item.title = 'Bus Plug'
})
item.title = "Bus Plug" doesn't check for equality, it sets item.title to "Bus Plug".
you have to change this line to this:
return item.title === 'Bus Plug'

Try rewriting item.details to a function:
details: () => (
<div>
<ul></ul>
<img src={`${categoryImagesDir}fuse-large.jpg`} />
</div>
)

Related

How to send a property from an array of object from a child component to the parent component?

I have App, that is the parent component and I have the Child component:
The Child component gets a props called items so it can be reused depending on the data. It the example there is data, data1 and data2.
The thing is that I want to set a cookie from the parent component, to set the cookie I need the property link from data2, but I am already mapping data2 in the Child component.
What can I do to obtain the value of the property link in the parent component to pass it as an arguement here:
<Child
onClick={() =>
handleUpdate('How can I obtain here the string from link of data2?')
}
items={data2}
/>
This is the whole example code:
import * as React from 'react';
import './style.css';
const data = [
{ title: 'hey', description: 'description' },
{ title: 'hey1', description: 'description' },
{ title: 'hey2', description: 'description' },
];
const data1 = [
{ title: 'hey', description: 'description' },
{ title: 'hey1', description: 'description' },
{ title: 'hey2', description: 'description' },
];
const data2 = [
{ title: 'hey', link: 'link/hey' },
{ title: 'hey1', link: 'link/he1' },
{ title: 'hey2', link: 'link/he2' },
];
export default function App() {
const [, setCookie] = useCookie('example');
const handleUpdate = (cookie) => {
setCookie(null);
setCookie(cookie);
};
return (
<div>
<h2>App - Parent</h2>
<Child items={data} />
<Child items={data1} />
<Child
onClick={() =>
handleUpdate('How can I obtain here the string from link of data2?')
}
items={data2}
/>
</div>
);
}
export function Child({ items }) {
return (
<div>
<h2>Child</h2>
<ul>
{items.map((item) => {
return (
<>
<p>{item.title}</p>
<a href={item.link}>Go to title</a>
</>
);
})}
</ul>
</div>
);
}
Thank you!
If you want to get the link from the Child component you can simply add a link parameter in the callback:
<Child
onClick={(link) => handleUpdate(link)}
items={data2}
/>
Then from the Child you just need to call the onClick prop:
export function Child({ items, onClick }) { // here make sure to add the prop while destructuring
<a href={item.link} onClick={() => onClick(item.link)}>Go to title</a>
The map method doesn't change the array that it is called on, it just returns a new array, do the items array doesn't get affected at all here, so you can just call it normally like so:
return (
<div>
<h2>App - Parent</h2>
<Child items={data} />
<Child items={data1} />
<Child
onClick={() =>
handleUpdate(data2[0].link)
}
items={data2}
/>
</div>
);
Also, your Child component needs to accept the onClick function as a prop like so:
export function Child({ items, handleClick }) {
return (
<div onClick={handleClick}>
<h2>Child</h2>
<ul>
{items.map((item) => {
return (
<>
<p>{item.title}</p>
<a href={item.link}>Go to title</a>
</>
);
})}
</ul>
</div>
);
}

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

Use ternary operator to show specific items from state

I'm unable to show conditional output with the ternary operator. I want to pass a value to a function and show only related info from the state. My code:
import React, {useState} from 'react';
function Tasks({taskId, index}){
{task.parentId == taskId : } //Unable to code this.
return( //show only tasks where parentId == taskId
<div>
<div> {task.title} </div>
<div> {task.body} </div>
</div>
)
}
function App(){
const[tasks, setTasks] = useState([
{
taskId: 1,
title: 'Task1',
body: 'This is the body of the task1',
isComplete: false,
parentId: 0
},
{
taskId: 2,
title: 'Task2',
body: 'This is the body of the task2',
isComplete: false,
parentId: 1
},
{
taskId: 3,
title: 'Task3',
body: 'This is the body of the task3',
isComplete: false,
parentId: 1
},
{
taskId: 4,
title: 'Task4',
body: 'This is the body of the task4',
isComplete: false,
parentId: 3
}
])
return(
<div style={{marginLeft: 20}}>
<h1>ToDo</h1>
{tasks.map((task, index)=>
<Tasks
taskId=1
/>
)}
</div>
)
}
export default App;
So, I want to only show the tasks that have the parentId as 1. How should I go about this?
If you're trying to render only those tasks with the specified id, you may not have to use the ternary operator.
function renderTasks(id) {
return tasks
.filter(({ taskId }) => taskId == id)
.map(({ title, body }) => (
<div>
<div> {title} </div>
<div> {body} </div>
</div>
));
}
For the least modification to the code, you can return an empty fragment or null:
function Tasks({ task }) {
return task.parentId == task.taskId
? (
<div>
<div> {task.title} </div>
<div> {task.body} </div>
</div>
)
: null;
}
(make sure to use parentId, not pasrentId, and task.taskId, not taskId - you aren't passing task as a prop currently, so change the code to do so: <Tasks task={task} />)
But I think it'd make more sense to use .filter in the caller:
return (
<div style={{ marginLeft: 20 }}>
<h1>ToDo</h1>
{tasks
.filter(task => task.parentId === task.taskId)
.map(task => <Task task={task} />)
}
</div>
)
(since Tasks renders a single task, consider calling it Task instead of Tasks)

How do you display a filtered list based on a state created with use state?

I have some code in codesandbox that is made up of 4 divs, 2 with the category "Book" and 2 with the category "Article". Some buttons at the top should trigger if all the divs should be displayed, only the books, or only the articles. All the buttons show every div currently, so the page doesn't change and it looks like the state stays the same
Here is the code which is on the sandbox
App.js
import React, { useState } from "react";
/* import Container from './design/Container' */
import Test from "./Test";
const posts = [
{
title: "React Hooks",
content: "The greatest thing since sliced bread!",
category: "Book"
},
{
title: "Using React Fragments",
content: "Keeping the DOM tree clean!",
category: "Article"
},
{
title: "Angular Hooks",
content: "The greatest thing since sliced bread!",
category: "Book"
},
{
title: "Angular Fragments",
content: "Keeping the DOM tree clean!",
category: "Article"
}
];
export default function App() {
const [productItems, setProductItems] = useState(posts);
function handleButton(e) {
console.log(e.target.value);
if (e.target.value === "All") {
setProductItems(posts);
} else {
setProductItems(
posts.filter((p, i) => <div key={i}>p.category === e.target.value</div>)
);
}
setProductItems(posts);
console.log(productItems);
}
return (
<div>
<Test posts={productItems} handleButton={handleButton} />
</div>
);
}
Test.js
import React from "react";
function Post({ p,title, content, category }) {
return (
<React.Fragment>
<div>
<h3>{p.title}</h3>
<div>{p.content}</div>
<br />
<i>
in <b>{p.category}</b>
</i>
</div>
</React.Fragment>
);
}
export default function Test({handleButton, posts = [] }) {
return (
<React.Fragment>
<div>
<button value="All" onClick={handleButton}>
All
</button>
<button value="Book" onClick={handleButton}>
Book
</button>
<button value="Article" onClick={handleButton}>
Article
</button>
</div>
<div>
{posts.map((p) => {
return <Post key={p.title} p={p} />;
})}
</div>
</React.Fragment>
);
}
style.scss
.App {
font-family: sans-serif;
text-align: center;
}
You had a few things wrong, one was that you handleButton required an argument but you weren't passing one to it. You need to call it like onClick={(e) => handleButton(e)} another was that you set the state of product items again after your if statement. You had already set it to the filtered value, but then you overwrote it with the unfiltered value like setProductItems(posts); so you have to remove this line. Another was that your filter function didn't really make sense. I would look it up and learn more about it. It takes a function that returns a boolean; it doesn't return a div.
SOLUTION
(sandbox)
App.js
import React, { useState } from "react";
import Test from "./Test";
const posts = [
{
title: "React Hooks",
content: "The greatest thing since sliced bread!",
category: "Book"
},
{
title: "Using React Fragments",
content: "Keeping the DOM tree clean!",
category: "Article"
},
{
title: "Angular Hooks",
content: "The greatest thing since sliced bread!",
category: "Book"
},
{
title: "Angular Fragments",
content: "Keeping the DOM tree clean!",
category: "Article"
}
];
export default function App() {
const [productItems, setProductItems] = useState(posts);
function handleButton(e) {
console.log(e.target.value);
if (e.target.value === "All") {
setProductItems(posts);
} else {
setProductItems(posts.filter((p) => p.category === e.target.value));
}
console.log(productItems);
}
return (
<div>
<Test posts={productItems} handleButton={handleButton} />
</div>
);
}
Test.js
import React from "react";
const Post = ({ pa }) => {
return (
<React.Fragment>
<div>
<h3>{pa.title}</h3>
<div>{pa.content}</div>
<i>
in <b>{pa.category}</b>
</i>
</div>
</React.Fragment>
);
};
export default ({ posts = [], handleButton }) => (
<>
<div>
<button value="All" onClick={(e) => handleButton(e)}>
All
</button>
<button value="Book" onClick={(e) => handleButton(e)}>
Book
</button>
<button value="Article" onClick={(e) => handleButton(e)}>
Article
</button>
</div>
<div>
{posts.map((pa, i) => (
<Post key={i} pa={pa} />
))}
</div>
</>
);

How to render an array of objects in React?

could you please tell me how to render a list in react js.
I do like this
https://plnkr.co/edit/X9Ov5roJtTSk9YhqYUdp?p=preview
class First extends React.Component {
constructor (props){
super(props);
}
render() {
const data =[{"name":"test1"},{"name":"test2"}];
const listItems = data.map((d) => <li key={d.name}>{d.name}</li>;
return (
<div>
hello
</div>
);
}
}
You can do it in two ways:
First:
render() {
const data =[{"name":"test1"},{"name":"test2"}];
const listItems = data.map((d) => <li key={d.name}>{d.name}</li>);
return (
<div>
{listItems }
</div>
);
}
Second: Directly write the map function in the return
render() {
const data =[{"name":"test1"},{"name":"test2"}];
return (
<div>
{data.map(function(d, idx){
return (<li key={idx}>{d.name}</li>)
})}
</div>
);
}
https://facebook.github.io/react/docs/jsx-in-depth.html#javascript-expressions
You can pass any JavaScript expression as children, by enclosing it within {}. For example, these expressions are equivalent:
<MyComponent>foo</MyComponent>
<MyComponent>{'foo'}</MyComponent>
This is often useful for rendering a list of JSX expressions of arbitrary length. For example, this renders an HTML list:
function Item(props) {
return <li>{props.message}</li>;
}
function TodoList() {
const todos = ['finish doc', 'submit pr', 'nag dan to review'];
return (
<ul>
{todos.map((message) => <Item key={message} message={message} />)}
</ul>
);
}
class First extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [{name: 'bob'}, {name: 'chris'}],
};
}
render() {
return (
<ul>
{this.state.data.map(d => <li key={d.name}>{d.name}</li>)}
</ul>
);
}
}
ReactDOM.render(
<First />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Shubham's answer explains very well. This answer is addition to it as per to avoid some pitfalls and refactoring to a more readable syntax
Pitfall : There is common misconception in rendering array of objects especially if there is an update or delete action performed on data. Use case would be like deleting an item from table row. Sometimes when row which is expected to be deleted, does not get deleted and instead other row gets deleted.
To avoid this, use key prop in root element which is looped over in JSX tree of .map(). Also adding React's Fragment will avoid adding another element in between of ul and li when rendered via calling method.
state = {
userData: [
{ id: '1', name: 'Joe', user_type: 'Developer' },
{ id: '2', name: 'Hill', user_type: 'Designer' }
]
};
deleteUser = id => {
// delete operation to remove item
};
renderItems = () => {
const data = this.state.userData;
const mapRows = data.map((item, index) => (
<Fragment key={item.id}>
<li>
{/* Passing unique value to 'key' prop, eases process for virtual DOM to remove specific element and update HTML tree */}
<span>Name : {item.name}</span>
<span>User Type: {item.user_type}</span>
<button onClick={() => this.deleteUser(item.id)}>
Delete User
</button>
</li>
</Fragment>
));
return mapRows;
};
render() {
return <ul>{this.renderItems()}</ul>;
}
Important : Decision to use which value should we pass to key prop also matters as common way is to use index parameter provided by .map().
TLDR; But there's a drawback to it and avoid it as much as possible and use any unique id from data which is being iterated such as item.id. There's a good article on this - https://medium.com/#robinpokorny/index-as-a-key-is-an-anti-pattern-e0349aece318
Try this below code in app.js file, easy to understand
function List({}) {
var nameList = [
{ id: "01", firstname: "Rahul", lastname: "Gulati" },
{ id: "02", firstname: "Ronak", lastname: "Gupta" },
{ id: "03", firstname: "Vaishali", lastname: "Kohli" },
{ id: "04", firstname: "Peter", lastname: "Sharma" }
];
const itemList = nameList.map((item) => (
<li>
{item.firstname} {item.lastname}
</li>
));
return (
<div>
<ol style={{ listStyleType: "none" }}>{itemList}</ol>
</div>
);
}
export default function App() {
return (
<div className="App">
<List />
</div>
);
}
import React from 'react';
class RentalHome extends React.Component{
constructor(){
super();
this.state = {
rentals:[{
_id: 1,
title: "Nice Shahghouse Biryani",
city: "Hyderabad",
category: "condo",
image: "http://via.placeholder.com/350x250",
numOfRooms: 4,
shared: true,
description: "Very nice apartment in center of the city.",
dailyPrice: 43
},
{
_id: 2,
title: "Modern apartment in center",
city: "Bangalore",
category: "apartment",
image: "http://via.placeholder.com/350x250",
numOfRooms: 1,
shared: false,
description: "Very nice apartment in center of the city.",
dailyPrice: 11
},
{
_id: 3,
title: "Old house in nature",
city: "Patna",
category: "house",
image: "http://via.placeholder.com/350x250",
numOfRooms: 5,
shared: true,
description: "Very nice apartment in center of the city.",
dailyPrice: 23
}]
}
}
render(){
const {rentals} = this.state;
return(
<div className="card-list">
<div className="container">
<h1 className="page-title">Your Home All Around the World</h1>
<div className="row">
{
rentals.map((rental)=>{
return(
<div key={rental._id} className="col-md-3">
<div className="card bwm-card">
<img
className="card-img-top"
src={rental.image}
alt={rental.title} />
<div className="card-body">
<h6 className="card-subtitle mb-0 text-muted">
{rental.shared} {rental.category} {rental.city}
</h6>
<h5 className="card-title big-font">
{rental.title}
</h5>
<p className="card-text">
${rental.dailyPrice} per Night ยท Free Cancelation
</p>
</div>
</div>
</div>
)
})
}
</div>
</div>
</div>
)
}
}
export default RentalHome;
Try this:
class First extends React.Component {
constructor (props){
super(props);
}
render() {
const data =[{"name":"test1"},{"name":"test2"}];
const listItems = data.map((d) => <li key={d.name}>{d.name}</li>;
return (
<div>
{listItems}
</div>
);
}
}

Categories

Resources