0

I have a page called Games in my React app and my React Routes are in the App.js file. On that Games page, if I click myButton, I want it to go to another page called Analyze Game and then populate some variables there. But when I normally open Analyze Game (without clicking myButton), it defines and populates a bunch of state and variables. The reason is so that you can analyze a game you manually enter, rather than picking from the list on the Games page. So I am a bit puzzled on how I can transfer the game data from the Games page to the Analyze Game page and then populate some variables there only if someone came from the games page.

I found this link that shows you can use history.push to get some data that was passed from one page to another: React-router - How to pass data between pages in React?



But how do you then only populate the variables on the Analyze Game page if you came from the games page?

Would you set a flag or something? What is best practice?

Jon
  • 501
  • 3
  • 18
  • 1
    Does this answer your question? https://stackoverflow.com/questions/41966762/reactjs-how-to-transfer-data-between-pages/41966943 – isherwood Sep 17 '21 at 16:47
  • 1
    Or this? https://stackoverflow.com/questions/59701050/how-to-pass-data-from-a-page-to-another-page-using-react-router – isherwood Sep 17 '21 at 16:48

1 Answers1

1

This is a good question, and normally can be done in two ways. I'll briefly mention them. Of course, there're other ways ;)

props

React likes props, so if you can solve it with that, that should be your first approach.

  const App = () => {
    const [value, setValue] = useState(...)
    
    return (
      <Router>
         <Route1 render={() => <GamePage value={value} />} />
         <Route2 render={() => <AnalyzePage value={value} />} />
      </Router>
    )
  }

If you want to change this value inside either Game or Analyze, pass the setValue inside as well.

context

If you have very nested components inside the route, sometimes people like to use a context.

  const App = () => {
    const [value, setValue] = useState(...)
    
    return (
      <Context.Provider value={{ value, setValue}}>
        <Router>
          <Route1 render={() => <GamePage />} />
          <Route2 render={() => <AnalyzePage />} />
        </Router>
      </Context.Provider>
    )
  }

  const ComponentInsideGame = () => {
    const { value } = useContext(Context)
    ...
  }

global

If it turns out you want to send something behind React, for instance you don't want to trigger render at all for these shared data. You could do a global context with a ref.

  const App = () => {
    const ref = useRef({
      gameConfiguration: ...,
      runGame: () => {}
    ))
    
    return (
      <Router>
         <Route1 render={() => <GamePage />} />
         <Route2 render={() => <AnalyzePage />} />
      </Router>
    )
  }

  const ComponentInsideGame = () => {
    const { current } = useContext(Context)
    current.gameConfiguration = {...}
    current.runGame()
    ...
  }

route state

The link you provided is another way with browser state, however this actually isn't a react way, it's a browser way IMHO. But you know what, anyway works for you is fine :)

windmaomao
  • 7,120
  • 2
  • 32
  • 36
  • Thank you for that detail. Very useful to see the different ways. I have learnt from how you have structured that, by raising state to the App level, rather than page level. – Jon Sep 20 '21 at 13:00