Search code examples
reactjsreact-reduxreact-componentreact-statereach-router

How to pass data in react among different files or routes?


I'm new to react and after a beginners course of learning react. i decided to take a personal project of creating a monthly subscription app that'll help me keep track of all my subscriptions. However, i'm stuck at a point where i need to pass the state of one component into another but that other component is accessible through a route, btw i'm using reach router. is there any way that is possible. below is my code. So what i want to do basically is that when i click on of the subscriptions in my list, (say: Netflix) it should basically take me another page, and show me all the neccesary details regarding that subscription. Here i want state (mylist) to be passed.

App.js

const App = () => {
  return (
    <div className="container">
      <Router>
        <List path="/" />
        <Details path="/details/:sub" />
      </Router>
    </div>
  );
};

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

List.js

const List = () => {
  const [mylist, setList] = React.useState([]);
  const [value, setValue] = React.useState({
    subscription: "",
    startDate: "",
    paymentTime: 0,
  });

  const handleSubmit = (e) => {
    mylist.push(value);
    setList(mylist);
    setValue({ subscription: "", startDate: "", paymentTime: 0 });
    e.preventDefault();
  };
  const handleOnChange = (event) => {
    setValue({ ...value, [event.target.name]: event.target.value });
  };
  return (
    <div>
      <div className="for_list">
        <ul className="list">
          {mylist.map((obj) => (
            // <Link to={`/details/${obj.subscription}`} key={obj.subscription}>
            <li key={obj.subscription}>{obj.subscription}</li>
            /* </Link> */
          ))}
        </ul>
      </div>
      <div className="for_form">
        <form>
          <input
            type="text"
            name="subscription"
            onChange={handleOnChange}
            value={value.subscription}
          />
          <input
            type="date"
            name="startDate"
            onChange={handleOnChange}
            value={value.startDate}
          />
          <input
            type="number"
            name="paymentTime"
            onChange={handleOnChange}
            value={value.paymentTime}
          />
        </form>
      </div>
      <button onClick={handleSubmit}>Add Item</button>
    </div>
  );
};

export default List;

Details.js

const Details = (props) => {
  return (
    <div>
       Dunno what to do ;(
    </div>
  );
};
export default Details;

Solution

  • React Router uses location objects. One of the properties of a location object is state. You can pass some data field to state, then in your Details page, you will use these data fields to fetch data of each corresponding subscription.

    In your List.js:

    ...
    const handleSubmit = (e) => {
      e.preventDefault();
      mylist.push(value);
      setList(mylist);
      setValue({ subscription: "", startDate: "", paymentTime: 0 });
      props.histoty.push({
        pathname: '/details/netflix',
        state: {
          id: 'netflix-id',
        }
      })
    };
    ...
    
    export default withRouter(List);

    Then in your Details.js:

    import React, { useEffect, useState } from 'react'
    import { withRouter } from 'react-router-dom'
    
    const Details = (props) => {
      const [subInfo, setSubInfo] = useState({})
      useEffect(() => {
        fetch(`your-server-api/${props.state.id}`).then(res => res.json()).then(data => setSubInfo(data))
      }, [])
      return (
        <div>
           ...
        </div>
      );
    };
    export default withRouter(Details);

    One thing to keep in mind is that there will be no state if a user navigates directly to the page, so you will still need some mechanism to load the data when it does not exist.