Style properties on react components - reactjs

I have a component that is being repeated and the only reason its being repeated is because of the icon, color, and text.
import React from 'react';
const TabOne = () =>{
return (
<div className="irequest-tabs users">
<span className="tabOne"><i className="fa fa-sitemap navbuttonIcon" aria-hidden="true"></i>
<span className="hidden-sm hidden-xs">I want to...</span></span>
</div>
);
}
export default TabOne
I wanted to see if there was a way to make those properties on the component so that my component when used would look like:
<Tab1 color="#fff" icon="fa fa-sitemap" text="I want too..." />
I've tried:
import React from 'react';
const TabOne = () =>{
return (
<div style={{color: props.color}} className="irequest-tabs users">
<span className="tabOne"><i className={props.icon} className="navbuttonIcon" aria-hidden="true"></i>
<span className="hidden-sm hidden-xs">{props.text}</span></span>
</div>
);
}
export default TabOne

Almost there, just pass props as argument to TabOne (I'll simplify your markup for readability).
const TabOne = (props) => {
return (
<div style={{color: props.color}}>
<i className={props.icon}></i>
<span>{props.text}</span>
</div>
);
}
export default TabOne;
Remember, a functional component gets the properties passed by its parent as args to the function.

Related

Add element in array by button click

I have product cards that are rendered based on a json file.
By clicking on the "Add to Cart" button, the element should be added to the array сartList, but this does not happen.
I also tried to forward the function to the component itself, but it didn’t work out too well for me.
Shop.jsx:
import React, { useState } from 'react';
import './Instruments.css';
import Cart from '../components/Cart'
import Product from '../components/Product'
import cart from '../img/cart.png';
import data from "../data/data.json";
unction Shop() {
const [value, setValue] = useState('');
const [currentData, setCurrentData] = useState(data);
const [cartList, setCartList] = useState([]);
return (
<div className='shop'>
<div className='container'>
<div className='shop__main-products'>
{
currentData.filter((el) => {
return value.toLowerCase() === '' ? el : el.title.toLowerCase().includes(value.toLowerCase())
}).map((el, index) => {
return (
<Product img={el.img} title={el.title} price={el.price} key={el.id} onClick={() => setCartList([...cartList, el])}/>
)
})
}
</div>
</div>
<Cart active={modalActive} setActive={modalSetActive}/>
</div>
</div>
);
}
export default Shop;
Product.jsx:
import React, { useState } from 'react';
import './Product.css';
function Product({img, title, price, id, type}) {
return (
<div className='product' key={id} type={type}>
<div className='buy__top'>
<div className='product__top-image-background'>
<img className='product__top-image' src={img}></img>
</div>
<h3 className='product__top-title'>{title}</h3>
</div>
<div className='product__buy'>
<h3 className='product__buy-price'>{price} грн</h3>
<button className='product__buy-button'>В корзину</button>
</div>
</div>
)
}
export default Product;
It looks like the issue is with how you're passing the onClick function to the Product component. The onClick prop should be passed to the "Add to Cart" button, not the Product component itself. You should change the following line:
<Product img={el.img} title={el.title} price={el.price} key={el.id} addToCart={() => setCartList([...cartList, el])}/>
And in the Product component, you should add the onClick prop to the "Add to Cart" button:
<button className='product__buy-button' onClick={addToCart}>В корзину</button>
This way, when the button is clicked, it will call the addToCart function and add the element to the cartList array.
You are not adding the onClick function to the props of the Product component pass it down the pipe and itll work.
function Product({img, title, price, id, type, onClick}) {
return (
<div className='product' key={id} type={type}>
<div className='buy__top'>
<div className='product__top-image-background'>
<img className='product__top-image' src={img}></img>
</div>
<h3 className='product__top-title'>{title}</h3>
</div>
<div className='product__buy'>
<h3 className='product__buy-price'>{price} грн</h3>
<button className='product__buy-button' onClick={onClick}>В корзину</button>
</div>
</div>
)
}

How to pass a state (hook) between separated files (components) in React

Btw I already did a lot of research trying to solve this; So far I'm still stuck on this:
This is the first component in file1.jsx:
import * as React from 'react';
export default function MenuPopupState(props){
const [career, setCareer] = React.useState('');
return (
<div>
<button onClick={() => { setCareer(career) }}>
Press me
</button>
</div>
)
}
This is the another component in file2.jsx where I want to use the career state:
import * as React from 'react';
import MenuPopupState from './components/Menupopup';
export default function Header(){
const career = MenuPopupState.career;
return (
<div>
<a key={career.id}>
{career.name}
</a>
</div>
)
}
I tried differents methods, without reaching my goal of use the career.name in the Header
If state is shared between components, then you need to elevate that state to a common parent.
Then you can pass that state down to the children, probably as props or context.
For example:
function App() {
const [career, setCareer] = React.useState('');
return <>
<MenuPopupState career={career} onClick={setCareer} />
<Header career={career} />
</>
}
function MenuPopupState(props){
return (
<div>
<button onClick={() => props.onClick(props.career)}>
Press me
</button>
</div>
)
}
function Header(props){
return (
<div>
<a key={props.career.id}>
{props.career.name}
</a>
</div>
)
}

How to open dynamic modal with react js

I am trying to convert the HTML/Javascript modal to React js.
In Reactjs, I just want to open the modal whenever the user clicks the View Project button.
I have created a parent component (Portfolio Screen) and a child component (Portfolio Modal). The data I have given to the child component is working fine but the modal opens the first time only and then does not open. Another problem is that the data does not load even when the modal is opened the first time.
Codesandbox link is here.
https://codesandbox.io/s/reverent-leftpad-lh7dl?file=/src/App.js&resolutionWidth=683&resolutionHeight=675
I have also shared the React code below.
For HTML/JavaScript code, here is the question I have asked before.
How to populate data in a modal Popup using react js. Maybe with hooks
Parent Component
import React, { useState } from 'react';
import '../assets/css/portfolio.scss';
import PortfolioModal from '../components/PortfolioModal';
import portfolioItems from '../data/portfolio';
const PortfolioScreen = () => {
const [portfolio, setportfolio] = useState({ data: null, show: false });
const Item = (portfolioItem) => {
setportfolio({
data: portfolioItem,
show: true,
});
};
return (
<>
<section className='portfolio-section sec-padding'>
<div className='container'>
<div className='row'>
<div className='section-title'>
<h2>Recent Work</h2>
</div>
</div>
<div className='row'>
{portfolioItems.map((portfolioItem) => (
<div className='portfolio-item' key={portfolioItem._id}>
<div className='portfolio-item-thumbnail'>
<img src={portfolioItem.image} alt='portfolio item thumb' />
<h3 className='portfolio-item-title'>
{portfolioItem.title}
</h3>
<button
onClick={() => Item(portfolioItem)}
type='button'
className='btn view-project-btn'>
View Project
</button>
</div>
</div>
))}
<PortfolioModal portfolioData={portfolio} show={portfolio.show} />
</div>
</div>
</section>
</>
);
};
export default PortfolioScreen;
Child Component
import React, { useState, useEffect } from 'react';
import { NavLink } from 'react-router-dom';
const PortfolioModal = ({ portfolioData, show }) => {
const portfolioItem = portfolioData;
const [openModal, setopenModal] = useState({ showState: false });
useEffect(() => {
setopenModal({
showState: show,
});
}, [show]);
return (
<>
<div
className={`portfolio-popup ${
openModal.showState === true ? 'open' : ''
}`}>
<div className='pp-inner'>
<div className='pp-content'>
<div className='pp-header'>
<button
className='btn pp-close'
onClick={() =>
setopenModal({
showState: false,
})
}>
<i className='fas fa-times pp-close'></i>
</button>
<div className='pp-thumbnail'>
<img src={portfolioItem.image} alt={`${portfolioItem.title}`} />
</div>
<h3 className='portfolio-item-title'>{portfolioItem.title}</h3>
</div>
<div className='pp-body'>
<div className='portfolio-item-details'>
<div className='description'>
<p>{portfolioItem.description}</p>
</div>
<div className='general-info'>
<ul>
<li>
Created - <span>{portfolioItem.creatDate}</span>
</li>
<li>
Technology Used -
<span>{portfolioItem.technologyUsed}</span>
</li>
<li>
Role - <span>{portfolioItem.Role}</span>
</li>
<li>
View Live -
<span>
<NavLink to='#' target='_blank'>
{portfolioItem.domain}
</NavLink>
</span>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</>
);
};
export default PortfolioModal;
You don't have to use one useState hook to hold all your states. You can and I think you should break them up. In the PortfolioScreen component
const [data, setData] = useState(null);
const [show, setShow] = useState(false);
I changed the function Item that is used to set the active portfolio item to toggleItem and changed it's implementation
const toggleItem = (portfolioItem) => {
setData(portfolioItem);
setVisible(portfolioItem !== null);
};
You should use conditional rendering on the PortfolioModal, so you won't need to pass a show prop to it, and you'll pass a closeModal prop to close the PortfolioModal when clicked
{visible === true && data !== null && (
<PortfolioModal
data={data}
closeModal={() => toggleItem()} // Pass nothing here so the default value will be null and the modal reset
/>
)}
Then in the PortfolioModal component, you expect two props, data and a closeModal function
const PortfolioModal = ({ data, closeModal }) => {
And the close button can be like
<button className="btn pp-close" onClick={closeModal}>
...

Split one react component into two

I would like to know how I should split this code into two separate components.
import React from "react";
const DropdownMenu = (props) => {
const DropdownItem = (props) => {
return (
<a href="#" className="menu-item">
<span className="icon-button">{props.rightIcon}</span>
{props.children}
</a>
);
};
return (
<div className="dropdown">
<DropdownItem>{props.companyName[0].name}</DropdownItem>
<DropdownItem>{props.companyName[1].name}</DropdownItem>
<DropdownItem>Settings</DropdownItem>
<DropdownItem>Testing</DropdownItem>
<DropdownItem>Get our App</DropdownItem>
<DropdownItem>Mobile</DropdownItem>
<DropdownItem>Log out</DropdownItem>
</div>
);
};
export default DropdownMenu;
I try to split them up by myself but then my dropdown menu breaks and instead of opening a container down, it opens container inside my navbar, I think the issue with {props.children} but I don't know exactly how to fix it.
After splitting components I want it to remain like on this screenshot
there is 2 problems with your code.
well first, don't ever create a component inside render function of another component.
second and root cause of your problem is you have 2 variables named "props" in same scope
const DropdownItem = (props) => {
return (
<a href="#" className="menu-item">
<span className="icon-button">{props.rightIcon}</span>}
{props.children}
</a>
);
};
const DropdownMenu = (props) => {
return (
<div className="dropdown">
<DropdownItem>{props.companyName[0].name}</DropdownItem>
<DropdownItem>{props.companyName[1].name}</DropdownItem>
<DropdownItem>Settings</DropdownItem>
<DropdownItem>Testing</DropdownItem>
<DropdownItem>Get our App</DropdownItem>
<DropdownItem>Mobile</DropdownItem>
<DropdownItem>Log out</DropdownItem>
</div>
);
};
export default DropdownMenu
that should fix it.
you should pass rightIcon to every DropdownItem component that it`s passed to it and better to named your props instead of passing them as children
first component:
const DropdownItem = ({ label, rightIcon=' ', href='' }) => {
return (
<a href={href} className="menu-item">
<span className="icon-button">{rightIcon}</span>
{label}
</a>
);
};
second component:
const DropdownMenu = (props) => {
return (
<div className="dropdown">
<DropdownItem
label={props?.companyName?.[0]?.name}
rightIcon="icon-name"
href="href for this item"
/>
<DropdownItem label={props?.companyName?.[1]?.name} rightIcon="second-icon-name"/>
<DropdownItem label="Settings" />
<DropdownItem label="Testing" />
<DropdownItem label="Get our App" />
<DropdownItem label="Mobile" />
<DropdownItem label="Log out" rightIcon='log-out-icon'/>
</div>
);
}

React: Limit action to a single component

This is a container:
render() {
return (
<div>
<ul className="list-group" id="contact-list">
{this.returnContactList().map(
(contact) =>
<li key={contact.date.N} className="list-group-item">
<ContactCard contact={contact} onFormSubmit={this.handleSubmit} summaryHidden={this.state.summaryHidden} />
</li>
)}
</ul>
</div>
);
}
This is what I have as a component:
import React from 'react';
import '../Contacts.css';
const ContactCard = ({ contact, onFormSubmit, summaryHidden }) => {
return (
<div>
<button onClick={onFormSubmit}>submit</button>
<div style={{ display: summaryHidden ? 'block' : 'none' }}>
Summary
</div>
</div>
)
}
export default ContactCard;
This renders list of contacts. But when I click button, the text Summary gets applied to all components. I want to limit it to a single component only. How to do that?
You only have one "summaryHidden" variable in your container. You need a separate one for each component (maybe store them on the contact objects in the map) if you want the summaries to be hidden in some components and not others.

Resources