#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>
Примечание
Если вы предпочитаете избегать этого синтаксиса троичного оператора по какой-либо причине, вы можете решить это с помощью переменных в логике компонента перед возвратом. Может быть чище в зависимости от сложности компонента.