0

My components are not rendering on "Link" clicks but the url route does change, and if I manually refresh the browser the correct page renders. I have a private route created for the '/' path that uses a redirect if the user is not authenticated and send them back to the login. I have had a similar app working before almost set up identically but with using context instead of redux. I have read that react-router-dom and redux don't exactly pair well together but I don't fully understand why, I tried linking it up to the npm package "History" but saw multiple ways it can be done and couldn't successfully make it work. I can provide any additional code/information needed. Big thanks in advance to anyone that can assist. Also here is a link to the full repo: https://github.com/AustinRobinsonDev/license

I should add I had withRouter() on my main components and it was changing the url but not the component and I removed withRouter() and it doesn't change the URL or component

Versions:

  • react-router-dom 5.2.0
  • react-dom 18.0.0
  • redux 4.1.2

index.js:

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import reportWebVitals from './reportWebVitals';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);

reportWebVitals();

here is my main app.js:

const App = () => {
  return (
    <Provider store={store}>
      <Router>
        <>
        <Navbar />
          <Switch>
            <Route exact path='/about' component={About} />
            <Route exact path='/register' component={Register} />
            <Route exact path='/login' component={Login} />
            <PrivateRoute exact path='/' component={Home} />
          </Switch>
        </>
      </Router>
    </Provider>
  );
}

export default App;

Navbar with the router Links:

const Navbar = ({auth, logout, clearLicense}) => {
    const onLogout = () => {
        logout();
        clearLicense();
    }
    const authLinks = (
        <>
            <li>Hello {auth.user && auth.user.name}</li>
            <li>
                <a onClick={onLogout} href="#!">
                    <span className="hide-sm">Logout</span>
                </a>  
            </li>
        </>
    )
    const guestLinks = (
        <>
            <li>
                <Link to='/register'>Register</Link>
            </li>
            <li>
                <Link to="/login">Login</Link>
            </li>
        </>
    )
    return (
        <div className='navbar bg-primary'>
            <h1>License Manager{' '}Icon</h1>
            <ul>
                {auth.isAuthenticated ? authLinks : guestLinks}
            </ul>
        </div>
    )
}

const mapStateToProps = state => ({
    auth: state.auth
});

export default connect(mapStateToProps, { logout, clearLicense })(Navbar);

and an example of a component that will not re render:

const Login = ({history, auth, setAlert, login}) => {

  useEffect(() => {
    if (auth.isAuthenticated) {
      history.push('/');
    }
    if (auth.error === 'Invalid Credentials') {
      console.log('error invalid credentials')
      setAlert(auth.error, 'danger');
      clearErrors();
    }
    // eslint-disable-next-line
  }, [auth.error, auth.isAuthenticated, history]);
  const [user, setUser] = useState({
    email: '',
    password: ''
  });

  const { email, password } = user;

  const onChange = e => setUser({ ...user, [e.target.name]: e.target.value });

  const onSubmit = e => {
    console.log('onSubmit clicked')
    e.preventDefault();
    if (email === '' || password === '') {
      setAlert('Please fill in all fields', 'danger');
    } else {
      login({
        email,
        password
      })
    }
  };

  return (
    <div className='form-container'>
      <h1>
        Account <span className='text-primary'>Login</span>
      </h1>
      <form onSubmit={onSubmit}>
        <div className='form-group'>
          <label htmlFor='email'>Email Address</label>
          <input
            id='email'
            type='email'
            name='email'
            value={email}
            onChange={onChange}
            required
          />
        </div>
        <div className='form-group'>
          <label htmlFor='password'>Password</label>
          <input
            id='password'
            type='password'
            name='password'
            value={password}
            onChange={onChange}
            required
          />
        </div>
        <input
          type='submit'
          value='Login'
          className='btn btn-primary btn-block'
        />
      </form>
    </div>
  );
};

const mapStateToProps = state => ({
  auth: state.auth
});

export default connect(mapStateToProps, {setAlert, login})(Login);
  • Could you show your index.jsx file? You don't need `export default connect(mapStateToProps, { logout, clearLicense })(Navbar);` in functional component. And though I am using redux and react-router-dom together in real app, there is no problem at all. – Liki Crus Apr 20 '22 at 04:02
  • I added the index.js, what is the alternative to the connect statement? – Austin Robinson Apr 20 '22 at 14:29

0 Answers0