简体   繁体   中英

How do I store a variable state across components in React

I currently have three different component like A,B,C and I need to pass information from A to C thru B. I am being able to pass but I am having problem when I press back button the values are lost, I also get some undefined errors:

This is how I am passing from cmp A to cmp B (how component A looks like):

 this.state = {
            selectedIndustry: '',
            selectedJob: '' 
 }

<Link to={{
          pathname: '/information-job',
          state: {industry: this.state.selectedIndustry, job: this.state.selectedJob}
                        }}>
          <Button className={"primaryBtn"}>
                Apply
          </Button>
</Link>



 onIndustryChangeOption(event) {
        this.setState({selectedIndustry: event.target.value});
    }

    onJobChangeOption(event) {
        this.setState({selectedJob: event.target.value});
    }

In component B at componentDidMound I have: console.log(this.props.location.state) // prints out both industry and job

The thing is when I go from this component B to C and then click back button, then this.props.location.state does not have any value, so basically i lost the values from goint to one component to another.

What is the best way to achieve such that I can still keep values even when I go back to the component

EDIT: working example: https://codesandbox.io/s/l50l0zxn6q

I would wrap everything in a Root component and only change the children of this Root component across urls.

What's going on is that when you click on your back button, this.props.location.state is obviously empty since you didn't pass anything with your prop.

A way to remedy this is to have a Root component that will keep some state across pages. You can use Redux for that if you want as well.

So what you want is something like this:

import React from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom"

// Link does not allow overriding onClick as it is used internally by react-router
// add div inside Link and add onClick prop to div
const A = props => (
  <div>
    <Link to='/B'>
      <div onClick={() => props.setRootState({ test: 'foo' })}>
        Go to /B
      </div>
    </Link>
    {JSON.stringify(props.rootState)}
  </div>
)

const B = props => (
  <div>
    <Link to='/A'>
      <div onClick={ () => props.setRootState({ test: 'bar' }) }>
        Go to /A
      </div>
    </Link>
    {JSON.stringify(props.rootState)}
  </div>
)

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

    this.state = {
      test: '',
    }
  }

  render() {
    const DefaultComp = () => <Link to="/A">go to A</Link>

    // don't forget to bind this to setState
    const PageA = () => <A rootState={this.state}
      setRootState={this.setState.bind(this)} />
    const PageB = () => <B rootState={this.state}
      setRootState={this.setState.bind(this)} />

    return (
        <Switch>
          <Route exact path="/" component={ DefaultComp } />
          <Route path="/A" component={ PageA } />
          <Route path="/B" component={ PageB } />
        </Switch>
    )
  }
}

ReactDOM.render(
  <Router>
    <Root />
  </Router>,
  document.getElementById("root")
);

Like that you have a persistent state across URLs that each page components can access and modify if need be.

Please let me know if I made a mistake, I have tried the code and the behavior is that the state will change when clicking on the Links but not on the back button of your browser. Also let me know if there's something that's hard to understand or if I completely misunderstood what you were asking for ;)

Cheers and good luck !

EDIT: converted code to react-router ; should be working as expected

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM