supasate / connected-react-router

A Redux binding for React Router v4
MIT License
4.73k stars 592 forks source link

Peer dependencies #587

Open andreizanik opened 1 year ago

andreizanik commented 1 year ago

Updated peer dependencies Support react 18.2.0 and react-redux 8.0.0 https://github.com/supasate/connected-react-router/issues/585 https://github.com/supasate/connected-react-router/issues/577

vlone310 commented 1 year ago

Please, check this PR

andreizanik commented 1 year ago

@vlone310 I think this project isn't supported I decided to try the package mentioned in the issue https://github.com/supasate/connected-react-router/issues/579

achepukov commented 1 year ago

Closes https://github.com/supasate/connected-react-router/issues/612, please merge it

andreizanik commented 1 year ago

Closes https://github.com/supasate/connected-react-router/issues/612, please merge it

Unfortunately, author of the repository has not been active for a long time

achepukov commented 1 year ago

maybe there is a fork with react v18 support?

avindra commented 1 year ago

The premise of this library is wrong/ obsolete. With the latest react router the hooks give you the values you need.

-- Sent from Mobile

achepukov commented 1 year ago

@avindra I have complex selectors, which filters data based on url params (?a=1&b=2). Moving this logic into the a component is not an option for me. Do you have a solution?

avindra commented 1 year ago

With useSelector, you can pass params as everything is in the same scope. Say for example you had a query param named userId that you wanted to use in your redux selector:

import React from 'react';
import { useParams } from 'react-router-dom';
import { useSelector } from 'react-redux';

const UserProfile = () => {
  const { userId } = useParams();
  const user = useSelector((state) => state.users[userId]);

  return (
    <div>
      <h1>{user.name}</h1>
      <p>Email: {user.email}</p>
      {/* Render more user details */}
    </div>
  );
};

export default UserProfile;

Keep in mind you can swap useParams with your own implementation or a third-party one like use-query-params.

avindra commented 1 year ago

If you still have a lot of class-based components (which BTW you should get rid of to keep on track with latest react)... then you can use withRouter to get what you need. E.g.,:

import React from 'react';
import { connect } from 'react-redux';
import { withRouter } from 'react-router-dom';

const UserProfile = ({ user }) => {
  return (
    <div>
      <h1>{user.name}</h1>
      <p>Email: {user.email}</p>
      {/* Render more user details */}
    </div>
  );
};

const mapStateToProps = (state, ownProps) => {
  const userId = ownProps.match.params.userId;
  return {
    user: state.users[userId],
  };
};

export default withRouter(connect(mapStateToProps)(UserProfile));
achepukov commented 1 year ago

@avindra yeah, thank, but this looks like workaround rather then good fix.

Moving this logic into the a component is not an option for me.

Cuz fix this way means that I add logic into the component which is needed only in selectors. I do not need those values in component, but in selectors only. That's why it's too early to say that

The premise of this library is wrong/ obsolete.

avindra commented 1 year ago

this looks like workaround

Happy to disagree. FWIW, I removed a hundred or so of these connected router hacks, dropped connected-react-router and the code became much clearer in a codebase with over 80K SLOC.

Once again, useParams is the best option. If you need a connected like approach, then use withRouter.

achepukov commented 1 year ago

@avindra

I removed a hundred or so of these connected router hacks

could you please explain in detail what exactly you did? I didn't get it. From the example you provided it looks like you did not remove the logic, but moved it into component instead.

avindra commented 1 year ago

If you use withRouter, everything is done within the selector (using ownProps to access router data).

As you noted, with the useParams approach, some of the code gets moved to the component.

If you need to abstract the selector to a separate function, I suggest creating a hook. I have provided an example for this case.


file: hook.js


import { useParams } from 'react-router-dom';
import { useSelector } from 'react-redux';

export function useUser() { const { userId } = useParams(); const user = useSelector((state) => state.users[userId]); return user; }


> file: Component.js
```jsx
import React from 'react';
import {useUser} from './hook.js'

const UserProfile = () => {
  const user = useUser();

  return (
    <div>
      <h1>{user.name}</h1>
      <p>Email: {user.email}</p>
      {/* Render more user details */}
    </div>
  );
};

export default UserProfile;
achepukov commented 1 year ago

@avindra thanks lot! This looks much better from what I thought initially. But again, create new hook just to filter the selector data based on query params looks less nice then incapsulate this logic in selectors.