Show sibling components reactJs - javascript

I'm new on react world, I would show components from sibling components.
I have parent component:
import Toast from './components/Toast/Toast'
class App extends Component {
constructor(){
super();
this.state = {
showToast:false
};
}
render() {
return (
<div id="cont">
<Toast showToast={this.state.showToast}/>
<Header />
</div>
);
}
}
In my Toast component:
class Toast extends Component {
constructor(props) {
super(props);
}
render() {
const showToast = this.props.showToast;
let toast = null;
if (showToast) {
toast = <div className="visible">Toast Ok</div>;
}else{
toast = null;
}
return (
<div>
{toast}
</div>
);
}
}
export default Toast;
And in my Header component I have:
class Header extends Component {
render() {
return (
<button> // With click, show toastComponents so setState parent </button>
)
}
So if I click on button I would set state key showToast for show my components.

You can pass a function down to your <Header> component, then call it when the button is clicked.
let showToast = () => this.setState({ showToast: true });
// ...
<Toast showToast={this.state.showToast}/>
<Header onClick={showToast}>
Then all you need to do is pass this prop through to the click handler inside <Header>.
<button onClick={this.props.onClick}>

Related

Passing Props to grandchild React

Child:
class Plus extends React.Component{
constructor(props){
super(props)
this.handleClick = this.handleClick.bind(this)
}
handleClick(){
console.log('It's Working!')
this.props.handleButtonChange()
}
render(){
return (
<div>
<i
className="fa fa-plus fa-2x"
onClick={() => this.handleClick()}
></i>
</div>
);
}
}
export default Plus;
Parent:
class NoteCreation extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div className="note-creation">
<form action="">
<Plus handleButtonChange={this.props.handleButtonChange} />
</form>
</div>
);
}
}
export default NoteCreation;
GrandParent Component:
class App extends React.Component {
constructor() {
super();
this.state = {
buttonStat : false
};
this.handleButtonChange = this.handleButtonChange(this);
}
handleButtonChange(){
this.setState({
buttonStat : true
})
}
render() {
return (
<div className="App">
<NoteCreation
handleButtonChange={this.handleButtonChange}
/>
</div>
);
}
}
export default App;
I simply want to pass the method handleButtonChange() from grandParent all the way to child (which is a button), as the button is clicked it triggers the click event which fires up this function making changes in grandparent component(i.e. setting button state)
where am i wrong at or this approach is completely wrong I am really new to react.
i am just want to set state in grandParent via child click event.
i keep getting this error TypeError: this.props.handleButtonChange is not a function
would appreciate any help
You have a typo in your top component
It should be
this.handleButtonChange = this.handleButtonChange.bind(this);
and not
this.handleButtonChange = this.handleButtonChange(this);
Alternatively you can declare your method like this
handleButtonChange = () => {
this.setState({
buttonStat : true
})
}
without using bind at all.
In grandParent component, you should bind it to current component by keyword bind to pass it through props.
this.handleButtonChange = this.handleButtonChange.bind(this);

How to call an event handler function from App.js in two other components

I created a reset function in App.js and want to call it by an onclick in two other components. the problem is that it works in one component but doesn't in the other.
Here are the codes snippets
App.js
import React from 'react';
import Result from './components/Result';
import GeneralResult from './components/GeneralResult';
class App extends Component {
constructor(props) {
super(props);
this.state = {
result: '',
counter: 0,
}
}
// Reset function
handleReset=()=>{
this.setState({
result: '',
counter: 0,
)}
renderResult() {
return (
<div>
<Result reset={()=>this.handleReset()} />
<GeneralResult back={()=>this.handleReset()} />
</div>
);
}
Result.js
first component making use of reset()
function Result(props) {
return (
<div>
<span>
<button onClick={props.reset}>Replay</button>
</span>
</div>
);
}
export default Result;
GeneralResult.js
second component making use of the reset
import React, { Component } from 'react';
export default class GeneralResult extends Component {
render() {
return (
<React.Fragment>
<h2>Congratulations you won!</h2>
<span>
<button onClick={props.back}> Back to Question</button>
</span>
</React.Fragment>
);
}
}
You can pass the handler as props, and render the component from the parent class.
class Child extends Component {
render(){
return(
<button onClick = {this.props.onClick}></button>
)
}
}
export default Child;
import Child from 'path/to/child';
class Parent extends Component {
onClick = (e) => {
//do something
}
render () {
return(
<Child onClick = {onCLick}/>
)
}
}
Problem is that GeneralResult is class based component. so when you need to access props passed to it. you have to use this.props.
export default class GeneralResult extends Component {
render() {
return (
<React.Fragment>
<h2>Congratulations you won!</h2>
<span>
// you need to change "props.back"
// to "this.props.back"
<button onClick={this.props.back}> Back to Question</button>
</span>
</React.Fragment>
);
}
}

how to access refs in parent when child component is exported with withStyles?

for eg.
Child.js
//assume there is s as styles object and used in this component
class Child extends Component {
render() {
return (
<h1 ref={(ref)=>{this.ref = ref}}>Hello</h1>
);
}
}
export default withStyles(s)(Child);
Parent.js
class Parent extends Component {
onClick() {
console.log(this.child) // here access the ref
console.log(this.child.ref) // undefined
}
render() {
return (
<div>
<Child ref={child => this.child = child} />
<button onClick={this.onClick.bind(this)}>Click</button>
</div>
);
}
}
due to with styles the whole this.child ref in the parent component is changed. Please help me out with a workaround for this, dropping the withStyles is not an option.
You can make use of an innerRef prop and use it to get the ref of the child like
class Child extends Component {
componentDidMount() {
this.props.innerRef(this);
}
render() {
return (
<h1 ref={(ref)=>{this.ref = ref}}>Hello</h1>
);
}
}
export default withStyles(s)(Child);
and in parent
class Parent extends Component {
onClick() {
console.log(this.child) // here access the ref
console.log(this.child.ref) // undefined
}
render() {
return (
<div>
<Child innerRef={child => this.child = child} />
<button onClick={this.onClick.bind(this)}>Click</button>
</div>
);
}
}
Have your child component a prop with method onRef like follows:
class Child extends Component {
componentDidMount() {
this.props.onRef(this);
}
render() {
return (
<h1 ref={(ref) => { this.ref = ref }}>Hello</h1>
);
}
}
Then in your parent method you can access Child ref using callback as follows:
class Parent extends Component {
onClick() {
console.log(this.childHoc) // here access the withStyle ref
console.log(this.actualChild) // here access the actual Child Component ref
}
render() {
return (
<div>
<Child ref={childHoc => this.childHoc = childHoc} onRef={actualChild => this.actualChild = actualChild} />
<button onClick={this.onClick.bind(this)}>Click</button>
</div>
);
}
}

Change parent component state from child component

I know that the question with this title has already been asked few times before but the problem is that I couldn't get an appropriate answer. So as I am new to reactJS and trying to create login logout form.
What I want to do is to pass or change a state of parent component from a child component through an event handler(When a user clicks on logout button). Below are the two Components:
First One:
class Home extends React.Component {
constructor(props){
super(props);
this.state = {login : false};
}
login(){
// this method updates the login.state : true
}
render() {
return (
<div>
{this.state.login ? (<ChatBox userNick="fad" />) : (<LoginScreen onSubmit={this.login} />) }
</div>
);
}
}
And Second:
class ChatBox extends React.Component{
logout(){
// Expecting or trying to update parent.state.login : false
// via this method as well
}
render() {
return (
<div className="chat-box">
<button onClick={this.logout} > Logout </button>
<h3>Hi, {this.props.userNick} </h3>
</div>
);
}
}
I have simplified these component to come on point.
What's going here?
Home Component is the main parent component. Initially the state.login is false and in this situation LoginScreen Components shows up. Now, when user login through LoginScreen Component state.login updates to true, it's time to show for ChatBox Component.
Now you can see that ChatBox Component contains a button which calls a method logout to logout user. What I want is to update once again the state.login to false in Home Component When user click on the Logout Button.
I don't know how to do it, It will be appreciate if you help me.
Thanks in advance.
Do it in the same way as you are doing for Login, pass a function as a prop and call it on logout, see updates below.
const LoginScreen = () => (<div>Login Screen</div>);
class Home extends React.Component {
constructor(props){
super(props);
this.state = {login : true};
this.logout = this.logout.bind(this);
}
login(){
// this method updates the login.state : true
}
logout() {
// this method updates the login.state : false
this.setState({ login: false });
}
render() {
return (
<div>
{this.state.login ? (<ChatBox userNick="fad" onLogout={this.logout} />) : (<LoginScreen onSubmit={this.login} />) }
</div>
);
}
}
class ChatBox extends React.Component{
constructor(props) {
super(props)
// This makes sure `this` keeps pointing on this instance when logout is called from the outside.
this.logout = this.logout.bind(this);
}
logout(){
// Call the onLogout property.
this.props.onLogout();
}
render() {
return (
<div className="chat-box">
<button onClick={this.logout} > Logout </button>
<h3>Hi, {this.props.userNick} </h3>
</div>
);
}
}
ReactDOM.render(<Home />, document.querySelector('#main'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="main"></div>
You can pass an event from the Parent component to the Child component that handles the change of the state, like so:
class App extends React.Component {
constructor() {
super();
this.state = { isLoggedIn: false };
}
_handleLogin() {
this.setState({ isLoggedIn: true });
}
_handleLogout() {
this.setState({ isLoggedIn: false });
}
render() {
const { isLoggedIn } = this.state;
return (
<div>
{
isLoggedIn ?
<ChatBox logoutEvent={this._handleLogout.bind(this)} />
:
<Login loginEvent={this._handleLogin.bind(this)} />
}
</div>
);
}
}
const Login = ({ loginEvent }) => (
<button type="button" onClick={loginEvent}>Login</button>
);
const ChatBox = ({ logoutEvent }) => (
<div>
<h1>This is the Chat Box!</h1>
<button type="button" onClick={logoutEvent}>Logout</button>
</div>
);
ReactDOM.render(
<App />,
document.getElementById('container')
);
Here's the fiddle

How to call a component method from another component?

I have a header component that contain a button and I want this button to display another component(modal page) when it's clicked.
Can I do something like this:
Here's my header component:
import ComponentToDisplay from './components/ComponentToDisplay/index'
class Header extends React.Component {
constructor(props) {
super(props)
}
props : {
user: User
}
_handleInvitePlayerClick = () => {
this.refs.simpleDialog.show();
}
render(){
return(
<Button onClick={this._handleInvitePlayerClick} ><myButton/></Button>
<ComponentToDisplay />
)
}
}
Here is my component for the modal page that should be displayed when the button on the other component gets clicked:
class ComponentToDisplay extends React.Component {
componentDidMount() {
}
render() {
return (
<div>
<SkyLight
ref="simpleDialog"
title={"Title for the modal"}>
{"Text inside the modal."}
<Button onClick={() => this.refs.simpleDialog.hide()}>{"Close modal"}</Button>
</SkyLight>
</div>
)
}
}
Library being used for the modal : https://github.com/marcio/react-skylight
More like this:
class Header extends React.Component {
constructor(props) {
super(props)
}
props: {
user: User
}
render() {
return (
<Button onClick={() => this.refs.componentToDisplay.showMe()}><myButton /></Button>
<ComponentToDisplay ref="componentToDisplay" />
)
}
}
Being sure to expose a showMe() method on your child component:
class ComponentToDisplay extends React.Component {
showMe() {
this.refs.simpleDialog.show();
}
render() {
return (
<div>
<SkyLight
ref="simpleDialog"
title={"Title for the modal"}>
{"Text inside the modal."}
<Button onClick={() => this.refs.simpleDialog.hide()}>{"Close modal"}</Button>
</SkyLight>
</div>
)
}
}
Basically, what's going on here is you wrap the SkyLight's show() method in your child component's own method (in this case, showMe()). Then, in your parent component you add a ref to your included child component so you can reference it and call that method.

Categories