Когда пользователь нажимает на ссылку «Войти» в навигации, на странице отображается модальный режим. Навбар и модал содержатся в компоненте AppHeader
. Другой компонент с именем ActionBar
также имеет кнопку входа. Поэтому я использовал react-redux
для связи между различными компонентами. Вот моя реализация. (store.js
опущено.)
actionTypes. js
export const LOGIN_FORM_SHOW = 'LOGIN_FORM_SHOW'
действия. js
import { LOGIN_FORM_SHOW } from './actionTypes'
export const loginFormShow = () => ({
type: LOGIN_FORM_SHOW,
payload: {}
})
редуктор. js
import { LOGIN_FORM_SHOW } from './actionTypes'
const defaultState = {
loginFormVisible: false
}
export default function(state = defaultState, action) {
switch(action.type) {
case LOGIN_FORM_SHOW: {
return {
...state,
loginFormVisible: true
}
}
}
}
AppHeader. js
import React from 'react'
import LoginModal from '../components/LoginModal'
import {authService} from 'services/auth'
import { connect } from 'react-redux'
import {loginFormShow} from "../../redux/actions"
class AppHeader extends React.PureComponent {
constructor(props) {
super(props)
this.state = {
loginFormVisible: this.props.loginFormVisible ? true : false
}
this.showLoginModal = this.showLoginModal.bind(this)
}
showLoginModal() {
this.setState({
loginFormVisible: true
})
}
componentDidUpdate(prevProps, prevState, snapshot) {
if(this.props.loginFormVisible) {
this.showLoginModal()
}
}
render() {
return (
<>
// ... rest omitted
<nav><ul>
<li onClick={this.showLoginModal}>Login</li>
</ul></nav>
// ... ... ...
<LoginModal
open = {this.state.loginFormVisible}
onClose = { () => { this.setState(loginFormVisible: false) } }
/>
</>
)
}
}
const mapStateToProps = (state) => {
return {
loginFormVisible: state.loginFormVisible
}
}
export default connect(
mapStateToProps,
null
)(AppHeader)
ActionBar. js
import React from 'react'
import {loginFormShow} from "../../redux/actions"
import {connect} from "react-redux"
class ActionBar extends React.Component{
render() {
return (
<button onClick={this.props.loginFormShow}>Log In</button>
)
}
}
export default connect(
null,
{ loginFormShow }
)(ActionBar)
Кнопка входа в систему AppHeader
работает нормально. Но кнопка в ActionBar
показывает проблему.
Когда модальное имя входа отображается после нажатия кнопки в ActionBar
. Вы не можете закрыть модальный логин, потому что будет вызван метод componentDidUpdate
, а props.loginFormVisible будет всегда возвращать true .
Поскольку react-redux
доставляет состояние магазина как реквизиты, вы не можете изменить реквизит. Таким образом, вы не можете сказать, был ли обработан запрос от ActionBar
, и можно ли закрыть модальный вход prevProps
и props
всегда будут одинаковыми после первого нажатия кнопки в ActionBar
.
Я могу определить другой actionType LOGIN_FORM_CLOSE и исправить эту проблему, но я думаю, что там лежит некоторые ограничения из react-redux
.
Без использования actionType LOGIN_FORM_CLOSE мой обходной путь следующий:
AppHeader. js
componentDidUpdate(prevProps, prevState, snapShot) {
if((!prevProps.lastHandled || (this.props.lastHandled - prevProps.lastHandled)) && this.props.loginFormVisible) {
this.showLoginModal()
}
}
// ....
const mapStateToProps = (state) => {
const props = { loginFormVisible: state.loginFormVisible }
if (state.loginFormVisible) {
props.lastHandled= (new Date).getTime()
}
}
Почему react-redux
только отображает состояние магазина в реквизит? Вы не можете получить доступ к состоянию компонента в mapStateToProps
. Мне трудно пользоваться.