Reputation: 857
I have two components in my index.js file (Header and Sidebar) like below
import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import {
BrowserRouter as Router,
Route
} from "react-router-dom";
import './index.scss';
import './responsive.scss';
import Sidebar from './sidebar';
import Header from './header';
import Home from './home';
import Products from './products';
import Variant from './variant';
import Variety from './variety';
import * as serviceWorker from './serviceWorker';
ReactDOM.render(
<Router>
<div className="wrapper">
<Header />
<Sidebar />
<div id="content">
<Route exact path="/" component={Home} />
<Route path="/products" component={Products} />
<Route path="/variant" component={Variant} />
<Route path="/variety" component={Variety} />
</div>
</div>
</Router>
, document.getElementById('root'));
serviceWorker.unregister();
I have a button in my Header component and I want to add an onClick event handler to it, so when clicked the sidebar in Sidebar component would be toggled. Now my problem is that I can not connect these two components. I have even tried to use what is suggested in this link How To Pass Events Between Components, but the problem is that the event targets the change of all the elements defined in the children's components. I have read something about the createPortal() but it was suggested to access the DOM outside the component and since I am trying to access a component from another one I'm not sure if I should be doing that. Your help is appreciated in advance.
Upvotes: 4
Views: 3917
Reputation: 2361
First,simply about connecting these two components.The data transfer in React is suggested in pass from the father component to the child component.This is Lifting State Up.So normally, use callback to change the father component of header and pass the data back to sidebar.And now redux works well with react.So,simply set a state for Sidebar,and bind a function in onClick of Header.And add something in onClick.like this:
<header onClick = { this.expand.bind(this)} />
<sidebar sidebar = { this.state.sidebar} />
BTW,react provides us some ways to pass data.For example,context is used when component nesting is complex and it's hard to find the common father component.
Second,"the event targets the change of all the elements defined in the children's components".This problem is because of how the react works.You can use shouldComponentUpdate to avoid it.But not recommend here.
Third,about React Portal,it's added to React v16.It's used to render the child component outside the father component.This answer is good, if you want to know about it.How to use ReactDOM.createPortal() in React 16?. siderbar and header component are in the same levels.so I don't think it's nesscessary.
Upvotes: 1
Reputation: 677
As answered by everyone, these are some good solutions. But you have mentioned your constraints also. You can try below one also.
let showSidebar = true;
// Function to handle toggle
const handleClick = () => {
showSidebar = !showSidebar
renderApp()
}
// Make renderApp function
const renderApp = () => {
ReactDOM.render(
<Router>
<div className="wrapper">
<Header handleClick={handleClick}/> // call this function onClick inside your Header component
{ showSidebar && <Sidebar /> } // toggle the Sidebar
<div id="content">
<Route exact path="/" component={Home} />
<Route path="/products" component={Products} />
<Route path="/variant" component={Variant} />
<Route path="/variety" component={Variety} />
</div>
</div>
</Router>
, document.getElementById('root'));
};
renderApp(); // Call renderApp for the first time
serviceWorker.unregister();
Upvotes: 1
Reputation: 1424
There are few ways.
You can do something like following
// IN MAIN FILE
state ={
sidebarOpen : false
}
<header toggleSidebar = { this.toggleSidebar} />
<sidebar sidebarOpen = { this.state.sidebarOpen} />
toggleSidebar(){
//UPDATE STATE
this.setState({
sidebarOpen : !(this.state.sidebarOpen)
})
}
// IN HEADER
onButtonClick(){
this.props.toggleSidebar()
}
IN SIDEBAR
componentWillReceiveProps(props){
//LOGIC FOR UPDATING SIDEBAR YOU WILL RECIEVE UPDATED STATE HERE
}
Upvotes: 2
Reputation: 689
In order to connect components you should use a store to share the application state across all components. Something like Redux or similar would do it.
The main idea is that you change the state in the Header component, and Sidebar will be listening to this state and update itself if needed.
Upvotes: 2