当用户单击导航中的“登录”链接时,页面会显示一个模式。导航栏和模式包含在 AppHeader
组件中。
另一个名为 ActionBar
的组件也有一个登录按钮。所以我使用react-redux
在不同组件之间进行通信。
这是我的实现。 (store.js
被省略。)
actionTypes.js
export const LOGIN_FORM_SHOW = 'LOGIN_FORM_SHOW'
actions.js
import { LOGIN_FORM_SHOW } from './actionTypes'
export const loginFormShow = () => ({
type: LOGIN_FORM_SHOW,
payload: {}
})
reducer.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
将存储状态作为 props 提供,因此您无法修改 props。因此,您无法判断来自 ActionBar
的请求是否已实际处理,并且可以关闭登录模式。在 ActionBar
中第一次单击按钮后,prevProps
和 props
将始终相同。
我可以定义另一个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
只将存储状态映射到 Prop ?您无法在 mapStateToProps
中访问组件的状态。我觉得很难用。
最佳答案
您不需要 componentDidUpdate
。您可以根据 this.props.loginFormVisible
render() {
return (
<>
// ... rest omitted
<nav><ul>
<li onClick={this.showLoginModal}>Login</li>
</ul></nav>
// ... ... ...
{this.props.loginFormVisible && <LoginModal
open = {this.state.loginFormVisible}
onClose = { () => { this.setState(loginFormVisible: false) } }
/> }
</>
)
}
}
这是减少 componentDidUpdate
干扰的简单方法。您也可以摆脱 open
属性,并简化事情。
Redux 在尝试同步组件之间的状态时非常有用。因为您处于需要在至少 2 个组件之间共享状态的情况,并且这两个组件都需要能够更改和/或读取状态,所以我建议将 loginFormVisible
保留在您的商店的状态。我会将其视为两个组件中的 Prop ,并且仅通过操作来更改它。因此,执行 LOGIN_FORM_CLOSE
操作是个好主意。每当你有像 this.state = { loginFormVisible: this.props.loginFormVisible ? true : false }
,您需要重新考虑您希望状态存在的位置。就您而言,对于这个状态,它可能更好地完全在商店中管理。
关于javascript - 使用react-redux时,prevProps和this.props将始终在componentDidUpdate中返回相同的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60119675/