How Can I access a function through props in another component - reactjs

I have two components Checkout.js and Checklist.js
I have managed to pass data down form checklist to checkout but I have a function to remove item from checkout but i dont know how to access it through props.
How can i Access the removeFood function inside checkout component
My Checklist .js
import React from 'react';
import './componentStyle.css';
function CheckList(props) {
return <div className="checkoutList">
<form>
<div>
<label htmlFor="name">Food</label>
<input type="text" readOnly id='name' value={props.food}></input>
</div>
<div>
<label htmlFor="price">Price</label>
<input type="number" readOnly id='price' value={props.price}></input>
</div>
<div>
<label htmlFor="quantity">Quantity</label>
<input type="number" readOnly id='quantity' value={props.quant}></input>
</div>
<div>
<label htmlFor="total">Total</label>
<input type="number" readOnly id='total' value={props.total}></input>
</div>
</form>
<button style={{
cursor:"pointer"
}} onClick={} type='button'>Remove</button>
</div>;
}
export default CheckList;
My checkout.js
import React from 'react';
import {useState, useEffect} from 'react';
import CheckList from '../components/CheckList';
import Data from '../data.json';
import OrderBtn from '../components/TrayOrderBtn';
function Checkout(props) {
const foodItem = (
Data.myTray.map((item) => <CheckList id={item[Math.random().toString().slice(2)]} key={item.id} food={item['food']} price={item['price']} quant={item['quantity']} />)
)
var [widget, setWidget] = useState(Data.myTray);
const removeFood=(item)=> {
widget.filter((w) => w.id !== item.id)
}
console.log(widget)
useEffect(() => {
setWidget(Data.myTray)
},[widget])
if (Data.myTray.length <= 0) {
return <div>
<h1>Add a Food Item to Your Tray</h1>
</div>
}else {
return <div className="checkout">
{widget.map(
(item) => <CheckList key={item.id} food={item['food']} price={item['price']} quant={item['quantity']} />
)}
<OrderBtn />
</div>;
}
}
export default Checkout;

Take a look at the example below-
Suppose you have a component Checkout and you want to pass your delete function to Checklist component so that you can apply a event listener in Checklist component.
Here we are passing our delete function as a prop to Checklist component
Note: -This is just an example how you can implement.
See our Checkout Component
export default function Checkout(){
const handleDelete=(data)=>{
console.log(data);
}
return(
<Checklist handleDelete={handleDelete}/>
)
}
See our Checklist Component
export default function Checklist(props){
return(
<button onclick={()=>props.handleDelete("your target id or anything")}>Delete</button>
)
}

Here is a minimal reproducible example. The add and remove functions are defined in App and passed down to children components Products and Checkout accordingly. Run the code and click some carrot and banana into your cart. Then click ❌ to remove some.
function App() {
const [cart, setCart] = React.useState([])
const add = item => e =>
setCart([...cart, item])
const remove = index => e =>
setCart([...cart.slice(0, index), ...cart.slice(index+1)])
return <div>
<Products add={add} />
<Checkout cart={cart} remove={remove} />
</div>
}
function Products({ add }) {
const PRODUCTS = ["apple", "banana", "carrot"]
return <div className="products">
{PRODUCTS.map((p, key) =>
<button key={key} type="button" onClick={add(p)} children={p} />
)}
</div>
}
function Checkout({ cart, remove }) {
return <div className="checkout">
{cart.map((c, key) =>
<div>{c} <button type="button" onClick={remove(key)} children="❌"/></div>
)}
</div>
}
ReactDOM.render(<App/>, document.querySelector("#app"))
.products, .checkout { display: flex; flex-direction: flex-row; flex-wrap: wrap; }
.products > button { padding: 0.5rem; margin: 0.5rem; }
.checkout > div { background-color: #CDECFF; padding: 0.5rem; margin: 0.5rem; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script>
<div id="app"></div>
See Lifting State Up in the React Docs for additional examples.

Related

How can we create a editable `<code>` tag on fly and add different attributes to that

On click on Code button, how can we create a editable <code> tag on fly and add different attributes in react web app ?
Or may be an editable field display as code tag ? Could someone please advise here ?
import React, { useState } from 'react';
import { useNavigate } from "react-router-dom";
const Admin = () => {
const [createCode, setCreateCode] = useState("");
const navigate = useNavigate();
const createCodeSection = () => {
const newElement = React.createElement('code', {key: 'ele'+ new Date().getTime(), className:'codehighlight'}, `--sample code to enter-- `,);
setCreateCode(createCode => [...createCode, newElement]);
}
const handleLogout = () => {
localStorage.removeItem('loginEmail');
navigate("/login");
};
return (
<div id="App">
<div className='adminSection'>
<div className='row'>
<div className="logout">
<img src="/images/logout.png" alt="Logout" onClick={handleLogout}></img>
</div>
<div className='createBlogSection'>
<div className='row'>
<button onClick={createCodeSection}>Code</button>
<button>Image</button>
<button>Code</button>
</div> <br></br>
<textarea>
{createCode}
</textarea>
</div>
</div>
</div>
</div>
)
}
export default Admin;
css:
.codehighlight{
background-color: #353232;
color: #fff;
}

React change css style of a div in another component by button clicking in another component

on my Project I have a banner on top of my site with 2 buttons. when I click the button profile I want it to change the css style of a div in another component.
this is my code for the banner:
import Profile from "./Profile";
function Banner() {
const invis=false;
return (
<div className="banner">
<span className="bannerbtnsettings">
<button className="btnbannersettings">Settings</button>
</span>
<span className="bannerbtnprofile">
<button className="btnbannerprofile" onClick={Profile.changeStyle}>Profile</button>
</span>
</div>
);
}
export default Banner;
this is my code for the div in the other component:
import "../index.css";
import React, { useState } from "react";
const Profile = () => {
const [style, setStyle] = useState("profile-hidden");
const changeStyle = () => {
console.log("you just clicked");
setStyle("profile-displayed");
};
return (
<div>
<div className={style}> hellllo</div>
</div>
);
};
export default Profile;
I can only find information about this with parent-child components.
They said I should use a usestate import but I can't seem to get it working. what's the proper way to do this?
All you need is lift your state to parent component, if you have a long trip to your common ancestor you can try to use a context. Attached a working example. Hope it helps!
const Banner = ({ onClickHandler }) => {
return (
<div className="banner">
<span className="bannerbtnsettings">
<button className="btnbannersettings">Settings</button>
</span>
<span className="bannerbtnprofile">
<button className="btnbannerprofile" onClick={() => onClickHandler()}>Profile</button>
</span>
</div>
)}
const Profile = ({ style }) => {
return (
<div>
<div className={style}>I'm your profile :)</div>
</div>
);
};
const App = () => {
// We lift the state
const [style, setStyle] = React.useState("profile-hidden");
const profileHandler = () => {
setStyle(style === 'profile-hidden'
? 'profile-displayed'
: 'profile-hidden')
}
return(
<div>
<Banner onClickHandler={profileHandler} />
<Profile style={style} />
</div>
)
}
// Render
ReactDOM.createRoot(
document.getElementById("root")
).render(
<App />
);
.profile-hidden {
display: none;
}
.profile-displayed {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
<div id="root"></div>
You cannot use this syntax for React Components COMPONENT.method
, in your case onClick={Profile.changeStyle} !
Instead you should make Banner parent component and use Profile component as child inside it or vise versa !
then You should pass the state style as props so then you will be able to use its value.
your code should look like this :
function Banner() {
const [style, setStyle] = useState("profile-hidden");
const changeStyle = () => {
console.log("you just clicked");
setStyle("profile-displayed");
};
return (
<div className="banner">
<span className="bannerbtnsettings">
<button className="btnbannersettings">Settings</button>
</span>
<span className="bannerbtnprofile">
<button className="btnbannerprofile" onClick={changeStyle}>Profile</button>
</span>
<Profile style={style} />
</div>
);
}
export default Banner;
and your Profile component :
const Profile = (props) => {
return (
<div>
<div className={props.style}> hellllo</div>
</div>
)
}

Use same usestate hook for multiple icons

I have a two buttons in my react project (material ui icons) which are lowerarrow(both) and i made a use state and function to change upper arrow to lower arrow when it is clicked but i dont know how to use the same state for my another icon too, maybe using some id or something i dont know , right now i put {iconstate} in both the icons so both the icons are changing together i am trying to figure out how to change them individually without making new state and function here is my code :-
JSX:-
import React , {useState} from 'react';
import Weather_leftpanecss from './Weather_leftpane.module.css'
import KeyboardArrowDownIcon from '#mui/icons-material/KeyboardArrowDown';
import KeyboardArrowUpIcon from '#mui/icons-material/KeyboardArrowUp';
export default function Weather_leftpane() {
const [iconstate, seticonstate] = useState(<KeyboardArrowDownIcon/>)
const [valuestate, setvaluestate] = useState(true)
const togglearrow = ()=>{
if(valuestate==true){
seticonstate(<KeyboardArrowUpIcon/>)
setvaluestate(false)
}
else{
seticonstate(<KeyboardArrowDownIcon/>)
setvaluestate(true)
}
}
return <div>
<div className={Weather_leftpanecss.main}>
<div id={Weather_leftpanecss.item_1}>Weather</div>
<div id={Weather_leftpanecss.item_2}>
<input type="text" placeholder='Search for city..' />
</div>
<div id={Weather_leftpanecss.item_3}>
<div className={Weather_leftpanecss.item_3_content} id="item_3_1">
Cities
</div>
<div className={Weather_leftpanecss.item_3_content} id="item_3_2" onClick={togglearrow} >
{iconstate}
</div>
</div>
<div id={Weather_leftpanecss.item_4}>
<div className={Weather_leftpanecss.item_4_content} id="item_4_1">
Settings
</div>
<div className={Weather_leftpanecss.item_4_content} id="item_4_2" onClick={togglearrow}>
{iconstate}
</div>
</div>
</div>
</div>;
}
css:-
.App {
font-family: sans-serif;
text-align: center;
}
(not the real css ,just added it because i have included it everywhere in my code with module)
Here you need to save the selected Id in the state.
import React , {useState} from 'react';
import Weather_leftpanecss from './Weather_leftpane.module.css'
import KeyboardArrowDownIcon from '#mui/icons-material/KeyboardArrowDown';
import KeyboardArrowUpIcon from '#mui/icons-material/KeyboardArrowUp';
export default function Weather_leftpane() {
const [valuestate, setvaluestate] = useState(true)
const [id, setId] = useState(null);
const togglearrow = (val)=>{
if(valuestate==true){
setvaluestate(false)
}else{
setvaluestate(true)
}
setId(val);
}
return <div>
<div className={Weather_leftpanecss.main}>
<div id={Weather_leftpanecss.item_1}>Weather</div>
<div id={Weather_leftpanecss.item_2}>
<input type="text" placeholder='Search for city..' />
</div>
<div id={Weather_leftpanecss.item_3}>
<div className={Weather_leftpanecss.item_3_content} id="item_3_1">
Cities
</div>
<div className={Weather_leftpanecss.item_3_content} id="item_3_2" onClick={() => togglearrow('item_3_2')} >
{valuestate && id == 'item_3_2' ? KeyboardArrowUpIcon : KeyboardArrowDownIcon }
</div>
</div>
<div id={Weather_leftpanecss.item_4}>
<div className={Weather_leftpanecss.item_4_content} id="item_4_1">
Settings
</div>
<div className={Weather_leftpanecss.item_4_content} id="item_4_2" onClick={() => togglearrow('item_4_1')}>
{valuestate && id == 'item_4_1' ? KeyboardArrowUpIcon : KeyboardArrowDownIcon }
</div>
</div>
</div>
</div>;
}
Here you can use one state to achieve that, saving in one state the status of both buttons, which one is clicked or not and render the icon based on that status.
the toggleArrow function gets the itemId and uses it to set the updated value of the button. We use !prevState[itemId] since if it is false it will become true and vise versa.
I took the liberty of giving the state a more informative name than a generic name.
import React, { useState } from "react";
import Weather_leftpanecss from "./Weather_leftpane.module.css";
import KeyboardArrowDownIcon from "#mui/icons-material/KeyboardArrowDown";
import KeyboardArrowUpIcon from "#mui/icons-material/KeyboardArrowUp";
export default function Weather_leftpane() {
const [clickedButtons, setClickedButtons] = useState({
item_3_2: false,
item_4_2: false
});
const toggleArrow = (itemId) => {
setClickedButtons((prevState) => ({
...prevState,
[itemId]: !prevState[itemId]
}));
};
return (
<div>
<div className={Weather_leftpanecss.main}>
<div id={Weather_leftpanecss.item_1}>Weather</div>
<div id={Weather_leftpanecss.item_2}>
<input type="text" placeholder="Search for city.." />
</div>
<div id={Weather_leftpanecss.item_3}>
<div className={Weather_leftpanecss.item_3_content} id="item_3_1">
Cities
</div>
<div
className={Weather_leftpanecss.item_3_content}
id="item_3_2"
onClick={() => toggleArrow("item_3_2")}
>
{clickedButtons["item_3_2"] ? (
<KeyboardArrowUpIcon />
) : (
<KeyboardArrowDownIcon />
)}
</div>
</div>
<div id={Weather_leftpanecss.item_4}>
<div className={Weather_leftpanecss.item_4_content} id="item_4_1">
Settings
</div>
<div
className={Weather_leftpanecss.item_4_content}
id="item_4_2"
onClick={() => toggleArrow("item_4_2")}
>
{clickedButtons["item_4_2"] ? (
<KeyboardArrowUpIcon />
) : (
<KeyboardArrowDownIcon />
)}
</div>
</div>
</div>
</div>
);
}

adding and removing a classList in react js

I am using functional component in react js , in the below code
the class right-panel-active is not being added / is undefined. Someone help to enable the class be added when the button is toggled
import React from 'react';
import './style.css';
import {
Modal,
DropdownMenu
} from '../MaterialUI';
/**
* #author
* #function Header
**/
const Header = (props) => {
const container = () => {
document.getElementById('container');
}
const signUpButton = () => {
container.classList.add('right-panel-active');
};
const signInButton = () => {
container.classList.remove('right-panel-active');
};
return (
<div className="header">
<div className="container" id="container">
<button className="ghost" id="signIn" onClick={signInButton} >Sign In</button>
</div>
<div className="overlay-panel overlay-right">
<p>Enter your personal details and start journey with us</p>
<button className="ghost" id="signUp" onClick={signUpButton} >Sign Up</button>
</div>
</div>
)
}
export default Header
You are not utilising any of React's functionality.
Read about state management in React
and Event Handlers in React
const Header = (props) => {
const [isContainerActive, setIsContainerActive] = React.useState(false);
const signUpButton = () => {
setIsContainerActive(false);
};
const signInButton = () => {
setIsContainerActive(true);
};
return (
<div className="header">
<div id="container" className={`container${isContainerActive ? " right-panel-active" : ""}`}>
<button className="ghost" id="signIn" onClick={signInButton}>Sign In</button>
</div>
<div className="overlay-panel overlay-right">
<p>Enter your personal details and start journey with us</p>
<button className="ghost" id="signUp" onClick={signUpButton}>Sign Up</button>
</div>
</div>
);
}
ReactDOM.render(<Header />, document.getElementById("root"));
.header {height: 120px;}
.container {float:left;}
.overlay-right {display: none;background: red;float:right;height:100%;}
.right-panel-active ~ .overlay-right {display: inline-block;}
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
PS: I also recommend https://www.npmjs.com/package/classnames , or the cx library for className management.
I think the best solution for this is to making a state and handle the style by a ternarian
function Welcome(props) {
const {name} = props;
return (
<h1 style={name === 'Sara' ? right-panel-active : right-panel-inactive}>Hello, {name}</h1>
)}
function App() {
return (
<div>
<Welcome name="Sara" />
</div>
);
}
This is the React way of doing,
You have to keep a local state (useState) and track the button click and based on the state change update the class to the container. You shouldn't directly change the DOM.
Click on the button to see the CSS is adding or not.
import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [isSignUp, setSignUp] = useState(true);
return (
<div id="container" className={isSignUp ? "right-panel-active" : ""}>
<button onClick={() => setSignUp(false)}>SignIn</button>
<button onClick={() => setSignUp(true)}>SignUp</button>
//for testing the change
{isSignUp ? "right-panel-active added" : "right-panel-active removed"}
</div>
);
}
Sample working code - https://codesandbox.io/s/fragrant-http-qo6du?file=/src/App.js
No need to add click event with vanilla js, you could add an React onClick event. You forgot to return the container.
// if you use curly braces you must return the value
const container = () => {
return document.getElementById('container');
};
// or skip the curly braces
const container = () =>
document.getElementById('container');

How to pass latest state to a Parent component from Child Component in react

I am working on a React project, In my project I have two components those are App and Child.
The app is Parent component and child is Child component.
Now I Changed state in Child component when I click the button on Child component.
Now my goal is how to pass latest state of the Child component for a Parent component button.
I am not getting how to do this, please help me
This is App.js
import React from 'react';
import './App.css';
import Child from './Child/Child';
function App() {
return(
<div className='container'>
<div className='row'>
<button className='btn btn-primary'>Click here</button>
<Child></Child>
</div>
</div>
)
}
export default App
This is Child.js
import React, { useState } from 'react';
import './Child.css';
function Child() {
const [color, setColor] = useState('yellow');
const [textColor, setTextColor] = useState('white');
return (
<div className='container'>
<div className='row'>
<button style={{ background: color, color: textColor }}
onClick={()=>{setColor("black");setTextColor('red')}}className='btn btn-danger mt-5'>Click here</button>
</div>
</div>
)
}
export default Child
If you feel that I am not clear with my doubt, please put a comment.
Thank you.
You can not pass data from children to parent, just store data in parent and pass it to children like below
function App() {
const [color, setColor] = useState('yellow');
const [textColor, setTextColor] = useState('white');
return (
<div className='container'>
<div className='row'>
<button className='btn btn-primary'>Click here</button>
<Child
color={color}
setColor={color => setColor(color)}
textColor={textColor}
setTextColor={textColor => setTextColor(textColor)}
/>
</div>
</div>
)
}
export default App
import React from 'react';
import './Child.css';
function Child(props) {
const {color, setColor, textColor, setTextColor} = props;
return (
<div className='container'>
<div className='row'>
<button style={{ background: color, color: textColor }}
onClick={()=>{setColor('red');setTextColor('black')}}className='btn btn-danger mt-5'>Click here</button>
</div>
</div>
)
}
export default Child
define a function in parent component to
receive an argument i.e., child state here as per you question
pass this function as a prop to the child component
call this function from child component before or after setting the its state, as needed in your context.
I have used this method many a times while building react apps.
Please accept this as answer if it helps you out.
If your Child component has complex logic that you don't want the Parent to be bothered with you can pass a callback from Parent to the Child:
function Child({ onColorChanged }) {
//The disadvantage of this is that you can't pass in
// default values for color and textColor from Parent
const [color, setColor] = React.useState('yellow');
const [textColor, setTextColor] = React.useState('white');
//When color or textColor changes call the onColorChanged
// callback/event handler
React.useEffect(
() => onColorChanged({ color, textColor }),
//the onColorChanged callback/event handler is
// a dependency of this effect, that is why
// Parent uses useCallback so it won't change
// when parent re renders
[color, textColor, onColorChanged]
);
return (
<div className="container">
<div className="row">
<button
style={{ background: color, color: textColor }}
onClick={() => {
//some complicated logic you don't want in the
// parent
setColor('black');
setTextColor('red');
}}
className="btn btn-danger mt-5"
>
Click here
</button>
</div>
</div>
);
}
function Parent() {
const [state, setState] = React.useState();
const onColorChanged = React.useCallback(
color => setState(old => ({ ...old, color })),
[]
);
console.log('state is now:', state);
return (
<div className="container">
<div className="row">
<button className="btn btn-primary">
Click here
</button>
<Child onColorChanged={onColorChanged}></Child>
</div>
</div>
);
}
ReactDOM.render(<Parent />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
If Child does not have complicated logic that you don't want in Parent you can just have Parent manage the state and pass a callback when something changes.
const colors = ['yellow', 'gold', 'black', 'white'];
function Child({ setColor, color: { color, textColor } }) {
return (
<div className="container">
<h1 style={{ background: color, color: textColor }}>
Hello world
</h1>
<label>
color
<select
value={color}
onChange={e => setColor('color', e.target.value)}
>
{colors.map(c => (
<option value={c} key={c}>
{c}
</option>
))}
</select>
</label>
<label>
text color
<select
value={textColor}
onChange={e =>
setColor('textColor', e.target.value)
}
>
{colors.map(c => (
<option value={c} key={c}>
{c}
</option>
))}
</select>
</label>
</div>
);
}
function App() {
const [state, setState] = React.useState({
color: 'yellow',
textColor: 'white',
});
const setColor = React.useCallback(
(key, value) =>
setState(old => ({ ...old, [key]: value })),
[]
);
return (
<div className="container">
<div className="row">
<Child setColor={setColor} color={state}></Child>
</div>
</div>
);
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Resources