How to change attribute of a child component from parent in React? - reactjs

I'm having a Child Component with img & h5 elements.I want to change the image and heading content in each component without rewriting the whole code of it.
Parent Component
import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import Child from "./services";
const Navbar = () => {
return (
<div className="d-flex flex-row justify-content-center">
<Child/>
<Child/>
<Child/>
<Child/>
</div>
);
};
export default Navbar;
Child component:
import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
const Child = (props) => {
return (
<>
<div className="ser-wrapper">
<img src="https://api.time.com/wp-content/uploads/2019/08/better-smartphone-photos.jpg" id="myImage"/>
<h5>Heading 1</h5>
</div>
</>
)
};
export default Child;
I tried sending images SRC as props but didn't work the way I wanted. I want to get different images and different heading content for each component.

Parent component
import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import Child from "./services";
const Navbar = () => {
return (
<div className="d-flex flex-row justify-content-center">
<Child heading="Heading 1" imgSrc="https://api.time.com/wp-content/uploads/2019/08/better-smartphone-photos.jpg" />
<Child heading="Heading 2" imgSrc="https://media.istockphoto.com/photos/coahuilan-box-turtle-picture-id93385233?k=20&m=93385233&s=612x612&w=0&h=7pdWzLGa-XzIdvPvUsXzF91RomisLiGPiDnlr3iP00A=" />
// ...etc
</div>
);
};
export default Navbar;
Child component
import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
const Child = (props) => {
return (
<>
<div className="ser-wrapper">
<img src={props.imgSrc} id="myImage"/>
<h5>{props.heading}</h5>
</div>
</>
)
};
export default Child;

you will need to pass props to the child component from parent component
Parent Component
import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
import Child from "./services";
const Navbar = () => {
return (
<div className="d-flex flex-row justify-content-center">
<Child title="Heading 1" imgSrc="img-url"/>
<Child title="Heading 2" imgSrc="img-url"/>
<Child title="Heading 3" imgSrc="img-url"/>
</div>
);
};
export default Navbar;
Child component:
import React from "react";
import "bootstrap/dist/css/bootstrap.min.css";
const Child = (props) => {
return (
<>
<div className="ser-wrapper">
<img src={props.imgSrc} id="myImage"/>
<h5>{props.title}</h5>
</div>
</>
)
};
export default Child;

There are multiple ways to solve this problem.
You can send array of imgSrc and heading to child component and child component will loop over all these and render all of them like:-
Parent Component
data = [
{
imgSrc:
'https://api.time.com/wp-content/uploads/2019/08/better-smartphone-photos.jpg',
heading: 'heading1',
},
{
imgSrc:
'https://api.time.com/wp-content/uploads/2019/08/better-smartphone-photos.jpg',
heading: 'heading2',
},
];
render() {
return (
<div>
<Child data={this.data} />
<p>Start editing to see some magic happen :)</p>
</div>
);
}
}
Child Component
<div>
{data.map((obj) => {
return (
<div className="ser-wrapper">
<img src={obj.imgSrc} id="myImage" />
<h5>{obj.heading}</h5>
</div>
);
})}
</div>
Working Example:- https://stackblitz.com/edit/react-ts-l8ubqc?file=index.tsx
Other way is to use <Child> component multiple times in parent component and pass data as props
Parent Component
<div>
<Child heading='headingName' imgsrc = 'srcurl'/>
<Child heading='headingName' imgsrc = 'srcurl'/>
.
.
</div>
Child Component
const {imgsrc,heading} = props
return (
<>
<div>
<img src={imgsrc} />
<h5>{heading}</h5>
</div>
</>
)

Related

Passing Data from Parent to Child In React

I am testing if I can pass data from the parent App.js to a child component named Contact. I want to pass data when clicking on a button.
Here is the App.js file:
import React, { useState } from 'react';
import { Button } from 'semantic-ui-react';
import './App.css';
import Header from './Components/Header';
import Tabs from './Components/Tabs';
import Footer from './Components/Footer';
import SimpleMap from './Components/SimpleMap';
import NewPatient from './Components/NewPatient';
import Contact from './Components/Contact';
function App() {
const [data,setData] = useState(false);
const parentToChild = () => {
setData("This is information from parent to child.");
}
return (
<div className="App">
<Header />
<Contact parentToChild={data} />
<Tabs>
<div label="Home" class="home-page">
<img src="https://news.usc.edu/files/2020/06/covid_vaccine_stock.jpg"></img>
</div>
<div label="New Patient">
<NewPatient />
</div>
<div label="Locations">
<SimpleMap />
</div>
<div label="Appointments">
</div>
</Tabs>
<Footer />
</div>
);
}
export default App;
Here is the child component I want the data to be displayed from the parent data when I click on the button:
import React from 'react';
import './footer.css'
function Footer({parentToChild})
{
return (
<div className="Footer">
<div className="container">
<div className="row">
<div className="col">
<h4 className="block ">About Us</h4>
</div>
<div className="col">
<h4 onClick={() => parentToChild(true)} className="block" >Contact</h4>
</div>
<div className="col">
<h4><a className="block" href={"https://www.cdc.gov/coronavirus/2019-ncov/faq.html"}>COVID-19 FAQ</a></h4>
</div>
<div className="col">
<h4 className="block"><a className="block" href={"https://www.cdc.gov/coronavirus/2019-ncov/if-you-are-sick/quarantine.html"}>CDC Guidelines</a></h4>
</div>
</div>
</div>
</div>
);
}
export default Footer;
I am testing this functionality because I want to eventually display a popup form when I click on a button. I want to use the data from the parent to trigger a popup in a child component. The following code says that parentToChild is not a function. Why do I get this error?
You need to pass your parentToChild function to your Footer Component:
<Footer parentToChild={parentToChild}/>
And if you want to show data from your child, you will need to declare it in your params:
const parentToChild = (input) => {
console.log('Info from child' ,input);
setData("This is information from parent to child.");
}
You must pass that information via props to the Footer component,
<Footer parentToChild={parentToChild} />
This will trigger the callback.
you can use state.
const [state, setState] = useState('')
App.js
const buttonThatYouWantTobeClicked = (dataShouldGotoComponent) => {
setState(dataShouldGotoComponent)
}
<Footer data={state}/>
then in footer.js you can check if value of props is not undefiend or null, so do something

How to pass an Array from Child component to Parent component using hooks in react

I am working on a React project I am trying to pass a data from Child component to Parent component, But I don't know how to pass data from Child component to Parent component.
This is App.js
import React from 'react';
import './App.css';
import Parent from './Parent/Parent';
function App() {
return (
<div className="container">
<div className='row'>
<div className='col-12'>
<Parent></Parent>
</div>
</div>
</div>
);
}
export default App;
This is Parent.js
import React, { useState } from 'react';
import './Parent.css';
import Child from '../Child/Child';
const Parent = () => {
return (
<div className='container'>
<div className='row'>
<div className='col-12'>
<div className='one'>
<Child></Child>
</div>
</div>
</div>
</div>
)
}
export default Parent
This is Child.js
import React from 'react';
import './Child.css';
const Child = () => {
const students = ['Jasmine', 'Stella']
return (
<div className='container'>
<div className='row'>
<div className='col-12'>
</div>
</div>
</div>
)
}
export default Child
You can pass the data from Child to Parent by calling a function passed from Parent with the data you want to send as a parameter - like an event handler callback.
Let's say if you want to send students of your Child component to Parent when you click on an element:
const Parent = () => {
const onUpdate = (data) => {
// use the data
};
return (
<div className='container'>
<div className='row'>
<div className='col-12'>
<div className='one'>
<Child update={onUpdate}></Child>
</div>
</div>
</div>
</div>
)
}
const Child = ({ update }) => {
const students = ['Jasmine', 'Stella']
return (
<div className='container'>
<div className='row'>
<div className='col-12'>
<button click={() => update(students)} />
</div>
</div>
</div>
)
}
But if you have to pass data between components nested deeply, you should consider to use Redux or Context.
To do this, You have two easiest ways,
Use React context
Use React prop callback
I suggest you use the first way and here is an example of implementing the redux context feature into your app based on your question's codes.
Demo

Pass props between siblings (React)

I've got this functional component
import React from 'react'
function Header(){
return(
<div className='header'>
<h2>Logo</h2>
<p>Log In</p>
</div>
)
}
export default Header
When I will clicked on "Log In" I want to change my background-color in this class in class 'MainContainer'. Im a beginner in React. How Can I do it?
import React from 'react'
import RegistrationForm from '../LoginPage/RegistrationForm'
import './style2.scss'
class Main extends React.Component{
constructor(param){
super(param)
}
render(){
return(
<div className="mainContainer">
<RegistrationForm/>
</div>
)
}
}
export default Main
EDIT: Here is the class where I called this classes:
import React from 'react'
import Header from './components/LoginPage/Header'
import Main from './components/LoginPage/Main'
function App() {
return (
<div>
<Header/>
<Main/>
</div>
)
}
export default App;
Props can be passed from parent to child, not between siblings. So make a state in the App component and pass it down to Main and Header.
App
function App() {
const [loggingIn, setLoggingIn] = React.useState(false);
return (
<div>
<Header setLoggingIn={setLoggingIn} />
<Main loggingIn={loggingIn} />
</div>
)
}
Main
class Main extends React.Component{
constructor(param){
super(param)
}
render(){
return(
<div className="mainContainer" style={{ background: this.props.loggingIn ? 'red' : 'inherit' }}>
<RegistrationForm/>
</div>
)
}
}
Header
function Header({ setLoggingIn }){
return(
<div className='header'>
<h2>Logo</h2>
<p onClick={() => setLoggingIn(true)}>Log In</p>
</div>
)
}

I have assigned a unique key prop bu keep getting the error

I keep getting the error below despite trying to set a unique key
index.js:1 Warning: Each child in a list should have a unique "key" prop....
DETAILS
I have a component that is rendering and am passing an key={id} to the child component the id is unique and will render through another prop but I keep getting an error. I think I'm doing something stupid but cannot figure it out
PARENT COMPONENT
import React, { Fragment } from 'react';
import ReactDOM from 'react-dom';
import Card from './card';
const CardsBlock = props => {
const cardRender = props.Cards.map(Cards => {
const { title, url, id } = Cards;
return (
<Fragment>
<Card key={id} id={id} title={title} url={url} />
</Fragment>
);
});
return (
<div
id='card-block'
className='blue container-thin cardblock '>
<h2>FACTS</h2>
{cardRender}
</div>
);
};
export default CardsBlock;
CHILD COMPONENT
import React from 'react';
import ReactDOM from 'react-dom';
import 'materialize-css';
const Card = props => {
//deconstruct props here
const { title, url, id } = props
return (
<div id={"card-"+id} className='blue lighten-3 card container-thin lighten-4'>
<div className='card-left'>
<i class='material-icons grey-text'>more_vert</i>
</div>
<div class='card-middle'>
<a href='http://www.jimmyyukka.com'>
<p>{title} </p>
</a>
</div>
<div className='card-right'>
<span>
<i class='material-icons grey-text'>mode_edit</i>
</span>
<span>
<i class='material-icons grey-text'>clear</i>
</span>
</div>
</div>
);
};
export default Card;
1.Don't need to define fragment if you are passing value to child component.
2.You can use destructuring as used or pass object and destructure inside child component.
Define like this using destructuring,
const CardsBlock = props => {
const cardRender = props.Cards.map(({title,url,id})=>
<Card key={id} id={id} title={title} url={url} />
);
return (
<div
id='card-block'
className='blue container-thin cardblock '>
<h2>FACTS</h2>
{cardRender}
</div>
);
};
import React, { Fragment } from 'react';
import ReactDOM from 'react-dom';
import Card from './card';
const CardsBlock = props => {
const cardRender = props.Cards.map(record=> {
const { title, url, id } = Cards;
return (
<Fragment>
<Card key={record.id} id={record.id} title={record.title} url={record.url} />
</Fragment>
);
});
return (
<div
id='card-block'
className='blue container-thin cardblock '>
<h2>FACTS</h2>
{cardRender}
</div>
);
};
export default CardsBlock;

react - children component not showing

I'm trying to insert a child component inside another child component, but my code is not working. Following codes are the structure i'm trying to build.
const AddProductPage= () => {
return (
<PageTemplate>
<ProductTemplate>
<AddProduct />
</ProductTemplate>
</PageTemplate>
);
};
const PageTemplate= ({children}) => {
return (
<div className={cx('pagetemplate')}>
<HeaderContainer />
<main>
{children}
</main>
<Footer />
</div>
);
};
class ProductTemplate extends Component {
render() {
return (
<div className={cx('product-template')}>
...
<div className={cx('display')}>
{this.props.children}
</div>
</div>
);
}
}
class AddProduct extends Component {
render() {
return (
<div className={cx('addproduct')}>
addproduct
</div>
);
}
}
I'm trying to insert AddProduct component in ProductTemplate component as a child, which is inserted in PageTemplate component as a child. AddProductPage, however, is not showing AddProduct component. I'd be grateful if anyone can help.
I've run your code. May be you'r missing default export statements.
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import AddProductPage from './AddProductPage';
ReactDOM.render(<AddProductPage />, document.getElementById('root'));
AddProductPage.js
import React from 'react';
import PageTemplate from './PageTemplate';
import ProductTemplate from './ProductTemplate';
import AddProduct from './AddProduct';
const AddProductPage= () => {
return (
<PageTemplate>
<ProductTemplate>
<AddProduct />
</ProductTemplate>
</PageTemplate>
);
};
export default AddProduct;
PageTemplate.js
import React from 'react';
const PageTemplate= ({children}) => {
return (
<div>
<main>
{children}
</main>
</div>
);
};
export default PageTemplate;
ProductTemplate.js
import React,{Component} from 'react';
class ProductTemplate extends Component {
render() {
return (
<div>
<div>
{this.props.children}
</div>
</div>
);
};
};
export default ProductTemplate;
AddProduct.js
import React, {Component} from 'react';
class AddProduct extends Component {
render() {
return (
<div>
addproduct
</div>
);
};
};
export default AddProduct;
Output is this :
addproduct
Here`s a Fiddle of your code
Works Fine!. I have removed cx API. I suppose the problem might be with className resolution. Check in the dom hierarchy weather the Children DOM Node exists and they have received their respective classnames.
const PageTemplate= ({children}) => {
return (
<div className={'pagetemplate'}>
<HeaderContainer />
<main>
{children}
</main>
<Footer />
</div>
);
};

Resources