0

Hello I am having trouble finding where I can call a route with push after authenticating the user

I did it using redux

my action:

const AuthenticateUser = (login, password) => {
    return dispatch => {
        dispatch (startAuth ());
        // fetching data
        api.post ('/ login', {login, password})
            .then (response => {
            localStorage.setItem ('token', response.data [0]);
            dispatch (userAuthenticated (response.data [1]))
        })
            .catch (err => {console.error (err);});
    }
}

export default AuthenticateUser;

my reducer:

const authReducer = (state = initialState, action) => {
    switch (action.type) {
        case USER_AUTHENTICATED:
            return {
                ... state,
                loading: false,
                authenticated: true,
                user: action.user,
            }
        case USER_FAILED_AUTH:
            return {
                ... state,
                loading: false,
                message: action.error

            }
        default:
        return state;
    }
}

and my form

const SignIn = (props) => {
  const classes = useStyles();
  const dispatch = useDispatch();
  const [login, setLogin] = useState('');
  const [password, setPassword] = useState('');
  const handleSubmit = (e) => {
    e.preventDefault()
    dispatch(auth(login, password))
  }
  return (
    <div className={classes.root}>

      <Grid container spacing={2} className={classes.gridMain}>

        <Grid item lg={12} md={12} sm={12} xs={12} align="center">
          <img src={require("../nodejs-icon.svg")} alt="bug" height={100} />
        </Grid>

        <Grid item lg={12} md={12} sm={12} xs={12} className={classes.TextField}>
          <form onSubmit={handleSubmit}>
            <TextField
              className={classes.input2}
              id="demo2"
              label="Usuário"
              variant="outlined"
              value={login}
              onChange={(e) => setLogin(e.target.value)}
              InputLabelProps={{
                classes: {
                  root: classes.label,
                  focused: classes.focusedLabel,
                  error: classes.erroredLabel
                }
              }}
              InputProps={{
                classes: {
                  root: classes.cssOutlinedInput,
                  focused: classes.cssFocused,
                  notchedOutline: classes.notchedOutline,
                },
                startAdornment: (
                  <InputAdornment position="start">
                    <PersonSharpIcon style={{ fontSize: 25, color: 'rgba(20, 176, 12,0.9)' }} />
                  </InputAdornment>
                )
              }}
            />
            <TextField
              className={classes.txtFd}
              id="demo2"
              label="Senha"
              variant="outlined"
              value={password}
              onChange={(e) => setPassword(e.target.value)}
              InputLabelProps={{
                classes: {
                  root: classes.label,
                  focused: classes.focusedLabel,
                  error: classes.erroredLabel
                }
              }}
              InputProps={{
                classes: {
                  root: classes.cssOutlinedInput,
                  focused: classes.cssFocused,
                  notchedOutline: classes.notchedOutline,
                },
                startAdornment: (
                  <InputAdornment position="start">
                    <LockSharpIcon style={{ fontSize: 25, color: 'rgba(20, 176, 12,0.9)' }} />
                  </InputAdornment>
                )
              }}
            />
            <ButtonBase variant="raised" disableFocusRipple="false" disableRipple="false" centerRipple="false">
              <Typography noWrap className={classes.labelForgot} variant="subtitle2">
                Esqueci minha senha
          </Typography>
            </ButtonBase>
            <Button type="submit" className={classes.button} variant="raised" disableFocusRipple="false" disableRipple="false" centerRipple="false">
              Entrar
        </Button>
          </form>
        </Grid>

I have a route and after I authenticate this user I wanted to send it to a route or display an error msg, but I don't know where in the code to do it and how I would get it.

my route

const AppRouter = () => (
  <BrowserRouter>
          <Route path="/xd" component={AuthPage} exact={true} /> 
          <Route path="/dashboard/addProduct" component={AddProduct} exact={true} /> 

  </BrowserRouter>
);
  • Why you don't pass the `push` function as an argument in your AuthenticateUser function(you can use camelCase for this function since it's not a component authenticateUser) ? and call it over there if the request succeeds? I'm assuming you're using react router so if you're using it you can use the withRouter wrapper to get it in your component and then pass it in. – jean182 Dec 11 '19 at 18:23
  • Yes i'm using a router browser i edited the answer with it could you help me how would i do this? –  Dec 11 '19 at 18:27
  • In your `SignIn` component you need to import this `import { withRouter } from "react-router";` after that you wrap your component for example like this `export default withRouter(SignIn);` and you will have in the props of the SignIn component the `history` prop which comes from the router and contains the `push` function, after that you can use that prop in your `handleSubmit` something like this `dispatch(auth(login, password, push))` – jean182 Dec 11 '19 at 18:35
  • and on my function i make this signin: const SignIn = (props) => { –  Dec 11 '19 at 18:55
  • i make this and my function sign in have push undefinied i give console.log on props and got this: / history: {length: 2, action: "POP", location: {…}, createHref: ƒ, push: ƒ, …} location: {pathname: "/xd", search: "", hash: "", state: undefined} match: {path: "/xd", url: "/xd", isExact: true, params: {…}} staticContext: undefined –  Dec 11 '19 at 18:56
  • You may use `useEffect` in `SignIn` component, which checks for flag `authenticated: true (which is passed via props)` and does the redirection. – sardok Dec 11 '19 at 19:02
  • @sardok u can post one reply with this bro? –  Dec 11 '19 at 19:08

2 Answers2

1

So this is in order to give you an answer that is readable instead of using the comments. In your SignIn component:

import { withRouter } from "react-router-dom";
const SignIn = (props) => {
 const { history } = props;
 const { push } = history;
 // more variables
 const handleSubmit = (e) => {
  e.preventDefault()
  // You pass the push function over here.
  dispatch(auth(login, password, push))
 }
// Rest of the logic
}
export default withRouter(SignIn);

The withRouter would give you all the props that are coming from react-router, this will allow you to use the history object, which contains the push function, to redirect the user to the page you want.

Then in your authenticate function which I'm guessing is the ´AuthenticateUser´ function you could do this:

const AuthenticateUser = (login, password, push) => {
return dispatch => {
    dispatch (startAuth ());
    // fetching data
    api.post ('/ login', {login, password})
        .then (response => {
        localStorage.setItem ('token', response.data [0]);
        dispatch (userAuthenticated (response.data [1]))
        // push goes here
        push("/your-awesome-route")
    })
        .catch (err => {console.error (err);});
}
}

export default AuthenticateUser;
jean182
  • 3,213
  • 2
  • 16
  • 27
  • Does this work on vanilla redux or does it need any middleware? – apokryfos Dec 11 '19 at 19:09
  • I believe the user in the question is using `redux-thunk` not sure tbh but it should work on any middleware, or without it, I do this all the times using ´redux-saga´ for example – jean182 Dec 11 '19 at 19:12
  • @Jean could you just ask me one more route question? –  Dec 11 '19 at 19:14
  • sure what is it? @MykonSpt – jean182 Dec 11 '19 at 19:15
  • i have a structure in my router browser where i have mine
    here I put all my content routes
    but I would need two routes that didn't display my navbar header footer but I can't do it here my pastebin: https://pastebin.com/Eiu53dk7
    –  Dec 11 '19 at 19:19
  • What do you mean by that? I don't understand you, you want to have two pages that don't show either the header and the footer? – jean182 Dec 11 '19 at 20:16
  • Yes, this I set my header and footer in my route file –  Dec 11 '19 at 20:46
  • https://stackoverflow.com/questions/59293847/react-router-show-only-route-without-components-defined-in-my-browser if u can help m e –  Dec 11 '19 at 20:49
0

You may use useEffect in SignIn component, which checks for flag authenticated: true (where this variable is passed via props) and does the redirection.

Something like that

  useEffect(() => {
    const { authenticated, navigation } = props;
    if (authenticated) {
        navigation.navigate(Routes.GoodPlace);
    }

  });
sardok
  • 1,086
  • 1
  • 10
  • 19