javascript access - How to update parent's state in React?




change router (7)

I found the following working solution to pass onClick function argument from child to the parent component:

Version with passing a method()

//ChildB component
class ChildB extends React.Component {

    render() {

        var handleToUpdate  =   this.props.handleToUpdate;
        return (<div><button onClick={() => handleToUpdate('someVar')}>Push me</button></div>
        )
    }
}

//ParentA component
class ParentA extends React.Component {

    constructor(props) {
        super(props);
        var handleToUpdate  = this.handleToUpdate.bind(this);
        var arg1 = '';
    }

    handleToUpdate(someArg){
            alert('We pass argument from Child to Parent: ' + someArg);
            this.setState({arg1:someArg});
    }

    render() {
        var handleToUpdate  =   this.handleToUpdate;

        return (<div>
                    <ChildB handleToUpdate = {handleToUpdate.bind(this)} /></div>)
    }
}

if(document.querySelector("#demo")){
    ReactDOM.render(
        <ParentA />,
        document.querySelector("#demo")
    );
}

Look at JSFIDDLE

Version with passing an Arrow function

//ChildB component
class ChildB extends React.Component {

    render() {

        var handleToUpdate  =   this.props.handleToUpdate;
        return (<div><button onClick={() => handleToUpdate('someVar')}>Push me</button></div>
        )
    }
}

//ParentA component
class ParentA extends React.Component { 
    constructor(props) {
        super(props);
    }

    handleToUpdate = (someArg) => {
            alert('We pass argument from Child to Parent: ' + someArg);
    }

    render() {
        return (<div>
            <ChildB handleToUpdate = {this.handleToUpdate} /></div>)
    }
}

if(document.querySelector("#demo")){
    ReactDOM.render(
        <ParentA />,
        document.querySelector("#demo")
    );
}

Look at JSFIDDLE

My structure looks as follows:

Component 1  

 - |- Component 2


 - - |- Component 4


 - - -  |- Component 5  

Component 3

Component 3 should display some data depending on state of Component 5. Since props are immutable, I can't simply save it's state in Component 1 and forward it, right? And yes, I've read about redux, but don't want to use it. I hope that it's possible to solve it just with react. Am I wrong?


-We can create ParentComponent and with handleInputChange method to update the ParentComponent state. Import the ChildComponent and we pass two props from parent to child component ie.handleInputChange function and count.

import React, { Component } from 'react';
import ChildComponent from './ChildComponent';

class ParentComponent extends Component {
  constructor(props) {
    super(props);
    this.handleInputChange = this.handleInputChange.bind(this);
    this.state = {
      count: '',
    };
  }

  handleInputChange(e) {
    const { value, name } = e.target;
    this.setState({ [name]: value });
  }

  render() {
    const { count } = this.state;
    return (
      <ChildComponent count={count} handleInputChange={this.handleInputChange} />
    );
  }
}
  • Now we create the ChildComponent file and save as ChildComponent.jsx. This component is stateless because the child component doesn't have a state. We use the prop-types library for props type checking.

    import React from 'react';
    import { func, number } from 'prop-types';
    
    const ChildComponent = ({ handleInputChange, count }) => (
      <input onChange={handleInputChange} value={count} name="count" />
    );
    
    ChildComponent.propTypes = {
      count: number,
      handleInputChange: func.isRequired,
    };
    
    ChildComponent.defaultProps = {
      count: 0,
    };
    
    export default ChildComponent;
    

For child-parent communication you should pass a function setting the state from parent to child, like this

class Parent extends React.Component {
  constructor(props) {
    super(props)

    this.handler = this.handler.bind(this)
  }

  handler(e) {
    e.preventDefault()
    this.setState({
      someVar: someValue
    })
  }

  render() {
    return <Child handler = {this.handler} />
  }
}

class Child extends React.Component {
  render() {
    return <Button onClick = {this.props.handler}/ >
  }
}

This way the child can update the parent's state with the call of a function passed with props.

But you will have to rethink your components' structure, because as I understand components 5 and 3 are not related.

One possible solution is to wrap them in a higher level component which will contain the state of both component 1 and 3. This component will set the lower level state through props.


<Footer 
  action={()=>this.setState({showChart: true})}
/>

<footer className="row">
    <button type="button" onClick={this.props.action}>Edit</button>
  {console.log(this.props)}
</footer>

Try this example to write inline setState, it avoids creating another function.

When ever you require to communicate between child to parent at any level down, then it's better to make use of context. In parent component define the context that can be invoked by the child such as

In parent component in your case component 3

     static childContextTypes = {
            parentMethod: React.PropTypes.func.isRequired
          };

           getChildContext() {
            return {
              parentMethod: (parameter_from_child) => this.parentMethod(parameter_from_child)
            };
          }

parentMethod(parameter_from_child){
// update the state with parameter_from_child
}

Now in child component (component 5 in your case) , just tell this component that it want to use context of its parent.

 static contextTypes = {
       parentMethod: React.PropTypes.func.isRequired
     };
render(){
    return(
      <TouchableHighlight
        onPress={() =>this.context.parentMethod(new_state_value)}
         underlayColor='gray' >


            <Text> update state in parent component </Text>


      </TouchableHighlight>
)}

you can find Demo project at repo


I found the following working solution to pass onClick function argument from child to the parent component with param:

parent class :

class Parent extends React.Component {
constructor(props) {
    super(props)

    // Bind the this context to the handler function
    this.handler = this.handler.bind(this);

    // Set some state
    this.state = {
        messageShown: false
    };
}

// This method will be sent to the child component
handler(param1) {
console.log(param1);
    this.setState({
        messageShown: true
    });
}

// Render the child component and set the action property with the handler as value
render() {
    return <Child action={this.handler} />
}}

child class :

class Child extends React.Component {
render() {
    return (
        <div>
            {/* The button will execute the handler function set by the parent component */}
            <Button onClick={this.props.action.bind(this,param1)} />
        </div>
    )
} }

Before I start, jQuery is a JavaScript library used for DOM manipulation. So you should not be using jQuery for a page redirect.

A quote from Jquery.com:

While jQuery might run without major issues in older browser versions, we do not actively test jQuery in them and generally do not fix bugs that may appear in them.

It was found here: https://jquery.com/browser-support/

So jQuery is not an end-all and be-all solution for backwards compatibility.

The following solution using raw JavaScript works in all browsers and have been standard for a long time so you don't need any libraries for cross browser support.

This page will redirect to Google after 3000 milliseconds

<!DOCTYPE html>
<html>
    <head>
        <title>example</title>
    </head>
    <body>
        <p>You will be redirected to google shortly.</p>
        <script>
            setTimeout(function(){
                window.location.href="http://www.google.com"; // The URL that will be redirected too.
            }, 3000); // The bigger the number the longer the delay.
        </script>
    </body>
</html>

Different options are as follows:

window.location.href="url"; // Simulates normal navigation to a new page
window.location.replace("url"); // Removes current URL from history and replaces it with a new URL
window.location.assign("url"); // Adds new URL to the history stack and redirects to the new URL

window.history.back(); // Simulates a back button click
window.history.go(-1); // Simulates a back button click
window.history.back(-1); // Simulates a back button click
window.navigate("page.html"); // Same as window.location="url"

When using replace, the back button will not go back to the redirect page, as if it was never in the history. If you want the user to be able to go back to the redirect page then use window.location.href or window.location.assign. If you do use an option that lets the user go back to the redirect page, remember that when you enter the redirect page it will redirect you back. So put that into consideration when picking an option for your redirect. Under conditions where the page is only redirecting when an action is done by the user then having the page in the back button history will be okay. But if the page auto redirects then you should use replace so that the user can use the back button without getting forced back to the page the redirect sends.

You can also use meta data to run a page redirect as followed.

META Refresh

<meta http-equiv="refresh" content="0;url=http://evil.com/" />

META Location

<meta http-equiv="location" content="URL=http://evil.com" />

BASE Hijacking

<base href="http://evil.com/" />

Many more methods to redirect your unsuspecting client to a page they may not wish to go can be found on this page (not one of them is reliant on jQuery):

https://code.google.com/p/html5security/wiki/RedirectionMethods

I would also like to point out, people don't like to be randomly redirected. Only redirect people when absolutely needed. If you start redirecting people randomly they will never go to your site again.

The next part is hypothetical:

You also may get reported as a malicious site. If that happens then when people click on a link to your site the users browser may warn them that your site is malicious. What may also happen is search engines may start dropping your rating if people are reporting a bad experience on your site.

Please review Google Webmaster Guidelines about redirects: https://support.google.com/webmasters/answer/2721217?hl=en&ref_topic=6001971

Here is a fun little page that kicks you out of the page.

<!DOCTYPE html>
<html>
    <head>
        <title>Go Away</title>
    </head>
    <body>
        <h1>Go Away</h1>
        <script>
            setTimeout(function(){
                window.history.back();
            }, 3000);
        </script>
    </body>
</html>

If you combine the two page examples together you would have an infant loop of rerouting that will guarantee that your user will never want to use your site ever again.







javascript reactjs react-native web-deployment