React Router sending a state

Viewed 61

I create a list of Clients, where the user clicks one of the Clients they will Link to the page and send the data as a state. I get the data from portfolio that I fetched before using Context

      {portfolio.map((data) => {
        const { id, name, image, logo, year, title, text, path } = data;
        return (
          <Link to={`/portfolio/${path}`} key={id} state={data}>
            <div
              className={`grid-item grid-item--${id}`}
              style={{
                backgroundImage: `url(${image})`,
                backgroundSize: "cover",
                backgroundPosition: "center center",
              }}
            >
              <img src={logo} alt={name} className="cls-logo" />
              <div className="cls-text">
                <div className="cls-text-wrapper">
                  <h1>{year}</h1>
                  <h3>{title}</h3>
                  <p>{text}</p>
                </div>
              </div>
            </div>
          </Link>
        );
      })}

It succeeds for a moment, then I added a Link to make it easier to navigate by adding the prev and next Client if they want to see it.

let data = useLocation();
const { id, name, logo, image, text, title, year } = data.state;

  const { portfolio } = useGlobalContext();
  let prev = id - 1;
  if (prev === 0 && portfolio !== []) {
    prev = portfolio.length - 1;
  }

  let next = id + 1;
  if (next > portfolio.length - 1 && portfolio !== []) {
    next = 1;
  }

The problems that I'm getting are:

  1. Seems that I cant use portfolio because it's undefined at the first, so React can't catch the values from it.

  2. If I comment the prev & next my code works just fine, and when I hit the refresh button it's also fine. But the problem is when I try to access it directly from the URL since I didn't send any data to the component.

Appreciate any kinda response, thanks before.

1 Answers

Since it appears you have access to the same portfolio array in the receiving component as the linking component, I suggest using the dynamic route param as a "search" key to find the matching portfolio element. This avoids the issue of needing the route state to be sent as that "state" is easily derived from the portfolio array and the current route path param.

Assuming the route path is declared as something like path="/portfolio/:path", use the useParams hook to get the currently matched path param and search the portfolio array.

Example:

const { path } = useParams();
const [ite, setItem] = useState();

const { portfolio } = useGlobalContext();

useEffect(() => {
  setItem(portfolio.find(item => item.path === path));
}, [path, portfolio]);

...

From here you can tweak your prev/next logic to update the route path and let react-router-dom and the useEffect hook rerender and load the correct portfolio item.

Related