Pass props between siblings (React) - reactjs

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>
)
}

Related

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

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>
</>
)

Creating A react component which can be nested

I am trying to create a component which can be reused in another component.Suppose i have a component like this
import React from 'react';
export default class Container extends React.Component {
render() {
return (
<div className='col-md-4/6/7'>
<div className='bg-dark'>
.......... Content Goes Here .............
</div>
</div>
);
}
}
Then i want to use the component like this...
import React from 'react';
export default class Container extends React.Component {
render() {
return (
<Container col md={4}>
.......... Content Goes Here .............
</Container>
);
}
}
I cant achieve that .It can be somewhat {this.state.children} but dont know how can achieve it
Simply edit the Container to render children:
import React from 'react';
export default class Container extends React.Component {
render() {
return (
<div className='col-md-4/6/7'>
<div className='bg-dark'>
{ this.props.children }
</div>
</div>
);
}
}
And then use it:
<Container col md={4}>
Hello, world!
</Container>
The children prop is explained in detail here: https://reactjs.org/docs/composition-vs-inheritance.html
Props.children
const Wrapper = (props) => <div>{props.children}</div>
const Inner = (props) => <Wrapper>some text or component</Wrapper>
Access using this.props.children because it's class based component. if it's functional component access using props.children
export default class Container extends React.Component {
render() {
return (
<div className='col-md-4/6/7'>
<div className='bg-dark'>
{this.props.children}
</div>
</div>
);
}
}

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>
);
};

How to structure component export without export default?

I am trying not to use export default in my components but rather export function..
My components are structured something like this:
function Hero(props) {
return (
<section className="hero">
<div className="wrapper">
<div className="content">
<h1>{props.title}</h1>
<p>{props.text}</p>
</div>
</div>
</section>
);
}
export default Hero;
when I do import {Hero} from './components/hero/hero.js' it works ok for this component, however if I have a component that is receiving props. Like this, it does not work:
export function Chart() {
return (
<section className="chart">
<div className="wrapper">
<h2>{this.props.children}</h2>
<div className="img-container">
<img className="desktop" src={chart} />
<img className="mobile" src={mobileChart} />
</div>
</div>
</section>
);
}
I am trying to avoid export default and avoid using something like
class Chart extends React.Component {
render() {
return (
<section className="chart">
<div className="wrapper">
<h2>{this.props.children}</h2>
<div className="img-container">
<img className="desktop" src={chart} alt="Mortgage Rate Comparison Chart"/>
<img className="mobile" src={mobileChart} alt="Mortgage Rate Comparison Chart"/>
</div>
</div>
</section>
);
}
}
export default Chart;
When I try to switch this I am getting an error, i'm not sure the proper syntax for exporting this way. It was a request made by my lead dev and he is out of office this week.
When you have one model per module, default exports are preferred as per ECMAScript
If your code is like this in the file:
ChartComponent.js
export function Chart(props) {
return (
<section className="chart">
<div className="wrapper">
<h2>{props.children}</h2>
<div className="img-container">
<img className="desktop" src={chart} />
<img className="mobile" src={mobileChart} />
</div>
</div>
</section>
);
}
You have to import it this way:
With export default
import Chart from "./ChartComponent";
Without export default
import { Chart } from "./ChartComponent";
<Chart>
<div>
child elements
</div>
</Chart>
This should pass the children into your component if you are listening for props.
If you have multiple components in single file, you can export them in these ways:
ExampleMultipleComponents.js
export const ComponentI = class ComponentI extends React.Component {....};
export const ComponentII = () => (<div> ... </div>);
or like:
const ComponentI = class ComponentI extends React.Component {....};
const ComponentII = () => (<div> ... </div>);
export {
ComponentII,
ComponentI,
}
And them import them like:
import { ComponentI, ComponentII } from './ExampleMultipleComponents';
Hope this is helpful!

Trying to rewrite App.js as a class

I am trying to re-write the entry point App.js javascript file as a class. I'm doing this because I want to call an onClick function when a user clicks on the log out link.
Here is the current code:
import React, { PropTypes } from 'react';
import { IndexLink, Link } from 'react-router';
const App = (props) => {
return (
<div>
<IndexLink className="mypad" to="home">Home</IndexLink>
<Link className="mypad" to="">Log Out</Link>
<br/>
<br/>
{props.children}
</div>
);
};
App.propTypes = {
children: PropTypes.element
};
export default App;
Here was my attempt at re-writing this as a class. It doesn't work. I get the error: 'ReferenceError: props is not defined'
class App extends React.Component {
constructor(props) {
super(props);
}
render(){
return (
<div>
<IndexLink className="mypad" to="home">Home</IndexLink>
<Link className="mypad" to="">Log Out</Link>
<br/>
<br/>
{props.children}
</div>
);
}
}
App.propTypes = {
children: PropTypes.element
};
export default App;
You need to do this.props once its a class
<div>
<IndexLink className="mypad" to="home">Home</IndexLink>
<Link className="mypad" to="">Log Out</Link>
<br/>
<br/>
{this.props.children}
</div>
when you write the component as a function, props gets passed in as an argument. When you do it as a class, props are bound to the instance of the component object.
add this => this.props.children

Resources