Перенаправление URL-адреса после входа в систему (react js)

#javascript #reactjs #ecmascript-6 #formik #yup

#javascript #reactjs #ecmascript-6 #formik #ага

Вопрос:

Я новичок в react js. Я застрял в этой проблеме на много дней. Я не знаю, как перенаправить на path / users при успешном входе в систему (ошибок проверки нет). Если что-то непонятно, пожалуйста, скажите мне. Я впервые задаю вопрос о stackoverflow. Пожалуйста, помогите: (

//app.js

 import React from "react"
import ValidationLog from "./ValidationLog"
import PostList from "./PostList"
import  {BrowserRouter as Router,Route,Switch,Redirect}  from "react-router-dom"

function App() {
  

  return (
    <Router>
      <div className="App">

        <Switch>
          <Route exact path="/" component={ValidationLog}></Route>
          <Route path="/users" component={PostList}></Route>
        </Switch>
          
      </div>
    </Router>
  )
  
}
export default App

 

//ValidationLog.js

 import React from "react"
import {Formik} from "formik"
import * as Yup from "yup"
import  {BrowserRouter as Router,Route,Switch,Redirect}  from "react-router-dom"


const ValidationLog = () => (
    
    <Formik 
    
     initialValues = {{email: "", password: ""}}
     onSubmit = {(values,{ setSubmitting}) => {
         setTimeout(() => {
            <Redirect to="/users" /> 
            
         }, 500);
     }}
     
     validationSchema = {Yup.object().shape({
        email: Yup.string()
            .email()
            .required("Required"),
        password: Yup.string()
            .required("No password provided")
            .min(8,"Password has to be at least 8 characters.")
     })
            
    }
    >
        {props => {
            const {
                values,
                touched,
                errors,
                isSubmitting,
                handleChange,
                handleBlur,
                handleSubmit
            } = props

            
            
            
            return (
                    
                    <div>
                        

                        <form autoComplete = "off" onSubmit = {handleSubmit}>
                            <h2 style={{fontSize: 22}}>Login to view our user pool</h2>
                            <label htmlFor="email">Email:</label>
                            <input type="text" value={values.email} name="email" onChange={handleChange} onBlur={handleBlur} placeholder="Enter your email" className={errors.email amp;amp; touched.email amp;amp; "error"}/>
                            {errors.email amp;amp; touched.email amp;amp; (<div className="input-feedback">{errors.email}</div>)}
                            <label htmlFor="email">Password:</label>
                            <input type="password" value={values.password} name="password" onChange={handleChange} onBlur={handleBlur} placeholder="Enter your password" className={errors.password amp;amp; touched.password amp;amp; "error"}/>
                            {errors.password amp;amp; touched.password amp;amp; (<div className="input-feedback">{errors.password}</div>)}
                            <button type="submit" disabled={isSubmitting}>Login</button>
                            
                        </form>

                    </div>
            )
        }}
    </Formik>
)


export default ValidationLog

 

Я попробовал следующее. Я попытался добавить <Перенаправление на /users/> в ValidationLog.js

  onSubmit = {(values,{ setSubmitting}) => {
         setTimeout(() => {
            <Redirect to="/users" /> 
            
         }, 500);
     }}
 

Я также попытался установить переменную islogin в ValidationLog.js и импортировать в app.js когда ошибок проверки нет, но islogin всегда имеет значение false в app.js .

//ValidationLog.js

 export let islogin = false
onSubmit = {(values,{ setSubmitting}) => {
         setTimeout(() => {
            islogin = true
            console.log(`Logged in ${islogin}`)
         }, 500);
     }}
 

//app.js

 import ValidationLog,{islogin} from "./ValidationLog"

<Route exact path="/">
  {islogin ? <Redirect to="/users" /> : null}
</Route>

 

Комментарии:

1. Вы можете перенаправить, присвоив новое значение глобальному окну. значение местоположения. location = '/users/' . Вы можете сделать это в своей функции обратного вызова login. Однако это подскажет браузеру перезагрузить страницу.

Ответ №1:

<Redirect ... /> это JSX-конструкция для создания компонента в этой позиции. Само по себе это ничего не делает в императивных путях кода, таких как ваш onSubmit обработчик.

То, что вы ищете, — это обязательная функция, которую вы можете вызывать вне дерева реакции. Как из-за useHistory перехвата от react-router.

 import { useHistory } from "react-router-dom";

...

const history = useHistory();

...

  onSubmit={() => history.push("/home")}
 

Более конкретно для вашего примера:

 const ValidationLog = () => {
  const history = useHistory();
  return (
    
    <Formik 
    
     initialValues = {{email: "", password: ""}}
     onSubmit = {(values,{ setSubmitting}) => {
         setTimeout(() => {
            history.push(...)
            
         }, 500);
     }}
...
 

Комментарии:

1. Спасибо за ваш ответ. Но я не уверен, что вы имеете в виду. Вы имеете в виду создать другую функцию в другом файле с помощью useHistory() ? Как я могу связать эти два файла?

2. Новый файл не требуется, просто измените свой ValidationLog компонент. Я отражу возможные изменения в ответе

3. Первоначально тег <div></div> находится в моем возврате. Куда я должен переместить часть? Извините, я действительно новичок в react.js .

4. Без обид, но вам, вероятно, следует ознакомиться с JavaScript, а затем реагировать. Потому что некоторые понятия не относятся к вашему первоначальному вопросу. Что касается ответа на ваш прямой вопрос: ValidationLog это функция со стрелкой, которая неявно возвращает (потому что у нее нет тела). Я изменил это на явный возврат, потому что нам нужен хук. Вот почему у вас «два возврата». Другой упомянутый вами возврат находится в другой функции со стрелкой (функция визуализации Formik).

5. Ваш комментарий действительно помогает мне понять некоторые концепции, которые я плохо изучил. Я не заметил, что есть разница между функцией стрелки с помощью {}. Еще раз спасибо за вашу доброту! Счастливого кодирования!

Ответ №2:

Вы можете сделать это с помощью withRouter

Импортируйте withRouter из react-router-dom и включите ваш компонент с помощью withRouter в экспорт.

Затем вы можете перемещаться, используя this.props.history.push(«/newurl»)

 import React from "react"
import {Formik} from "formik"
import * as Yup from "yup"
// import withRouter
import  {BrowserRouter as Router,Route,Switch,Redirect,withRouter}  from "react-router-dom"


const ValidationLog = (props) => (

<Formik 

 initialValues = {{email: "", password: ""}}
 onSubmit = {(values,{ setSubmitting}) => {
     setTimeout(() => {
        // this redirects to /users, make sure you get the import withRouter (check the last export line)
        props.history.push("/users");
        
     }, 500);
 }}
 
 validationSchema = {Yup.object().shape({
    email: Yup.string()
        .email()
        .required("Required"),
    password: Yup.string()
        .required("No password provided")
        .min(8,"Password has to be at least 8 characters.")
 })
        
}
>
    {props => {
        const {
            values,
            touched,
            errors,
            isSubmitting,
            handleChange,
            handleBlur,
            handleSubmit
        } = props

        
        
        
        return (
                
                <div>
                    

                    <form autoComplete = "off" onSubmit = {handleSubmit}>
                        <h2 style={{fontSize: 22}}>Login to view our user pool</h2>
                        <label htmlFor="email">Email:</label>
                        <input type="text" value={values.email} name="email" onChange={handleChange} onBlur={handleBlur} placeholder="Enter your email" className={errors.email amp;amp; touched.email amp;amp; "error"}/>
                        {errors.email amp;amp; touched.email amp;amp; (<div className="input-feedback">{errors.email}</div>)}
                        <label htmlFor="email">Password:</label>
                        <input type="password" value={values.password} name="password" onChange={handleChange} onBlur={handleBlur} placeholder="Enter your password" className={errors.password amp;amp; touched.password amp;amp; "error"}/>
                        {errors.password amp;amp; touched.password amp;amp; (<div className="input-feedback">{errors.password}</div>)}
                        <button type="submit" disabled={isSubmitting}>Login</button>
                        
                    </form>

                </div>
        )
    }}
</Formik>
)

// changes
export default withRouter(ValidationLog)
 

Комментарии:

1. Спасибо за ваш ответ, но, похоже, появится сообщение об ошибке, в котором говорится, что props не определен.

2. Упс, я забыл использовать props в качестве параметра для компонента, я внес необходимые изменения (const ValidationLog = (props) => ), теперь он должен работать.

3. Боже, это работает, большое спасибо, но не могли бы вы вкратце объяснить, как это работает? Я имею в виду, почему <перенаправление> не работает? Также, когда использовать withRouter?

4. <Перенаправление> работает только внутри блока <Переключатель>. Когда вы заключаете свой компонент в withRouter, вы получаете объект истории в реквизитах, который затем можно использовать для навигации

5. Я вижу! Вы имеете в виду, что при закрытии компонента с помощью withRouter реквизит станет путем истории из app.js верно? Большое спасибо!

Ответ №3:

<Redirect> компонентный подход здесь:

Используйте переменную состояния в вашем компоненте

 const [submitted, setSubmitted] = useState(false);
 

При отправке, если условия для перенаправления выполнены, установите для этой переменной состояния значение true

 setSubmitted(true);
 

В вашем компоненте JSX поместите <Redirect to="/users" /> условно зависящую от этой переменной состояния

 return <Fragment>
{ submitted 
? <Redirect to="/users" />
: <MyComponent ...> }
</Fragment>
 

Примечание

Если вы предпочитаете избегать этого синтаксиса троичного оператора по какой-либо причине, вы можете решить это с помощью переменных в логике компонента перед возвратом. Может быть чище в зависимости от сложности компонента.