【问题标题】:react redux how to trigger container function with action coming from non react component反应redux如何使用来自非反应组件的动作触发容器功能
【发布时间】:2018-07-21 00:26:52
【问题描述】:

我有一个通过单击非反应组件触发的登录对话框模式。

当点击非反应组件时,我设法调度动作并更新状态,所以信息在道具上可用,但我需要触发一个更新 CSS 等的函数,而我不能在里面做容器。

如果动作来自容器或其子容器,那将是微不足道的。

因此,在下面的 app.js 代码中,我试图在调度 SHOW_LOGIN 操作时触发 onLoginClick() 方法。

此外,this.state.message 应该在同一个 onLoginClick() 方法上使用 SHOW_LOGIN 的有效负载进行更新。

Redux 的 store.subscriber() 方法在状态更改时触发,但我不知道如何使它在这种情况下工作。

首先,它只在上游组件上可用,然后我仍然无法从 store.subscriber 触发 onLoginClick() 方法。

谢谢

非反应元素 utils.js

`//react files to enable #signin_button to activate popup

import { dispatch } from 'redux';
import { showLogin } from '../../client/login/actions/';
import { store } from '../../client/login/';

$("#signin_button").click(function(e) {
store.dispatch(showLogin());
.......`

/login/actions/index.js

export const SHOW_LOGIN = 'SHOW_LOGIN';

export function showLogin(){
  return {
    type: SHOW_LOGIN,
    payload: 'some text'
  }
}

/login/reducers/reducer_login.js

import { SHOW_LOGIN } from '../actions/index';

export default function (state = [], action){
    switch (action.type) {
        case SHOW_LOGIN:
            return [ ...state, action.payload ];
    }
   return state;
}

/login/reducers/index.js

import { combineReducers } from 'redux';
import LoginReducer from './reducer_login';
import RecoveryReducer from './reducer_recovery';
import SubmitRecoveryReducer from './reducer_submit_recovery';

const rootReducer = combineReducers({
    login: LoginReducer,
    recovery: RecoveryReducer,
    submit_recover: SubmitRecoveryReducer
});

export default rootReducer;

/login/containers/app.js

import React from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { showLogin, showRecovery, submitRecovery } from '../actions/index';
import Recovery from './recovery';
import SocialLogin from './social_login';

class LoginPopup extends React.Component{

    constructor(props){
       super(props);
       this.state = { 
         error : false, 
         emailRecovery:  '',
         message: 'some message'
      };
      this.recovery = this.recovery.bind(this);
      this.onRecoveryChange = this.onRecoveryChange.bind(this);
      this.onSubmitRecovery = this.onSubmitRecovery.bind(this);
   }
recovery() {
  //handles showing recovery password dialog 
}

onRecoveryChange(event){
    this.setState({emailRecovery: event.target.value});
}

onSubmitRecovery(event){
   //handles recovery password request
}

onLoginClick(){
   //*** handles CSS and other when non-react component clicked ***
}

render(){
    console.log(this.props.login);

    return (
        <div id="popup_sign" style={{display:'none'}} >
            <h4 className="account_notice">
                {this.state.message}
            </h4>
            <div id="login">
                <SocialLogin error={this.state.error} recovery={this.recovery}/>
                <button id="ok_login"  className="sub_ok btn btn-sm" type="button" >OK</button>
            </div>
            <Recovery 
                submitRecovery={this.onSubmitRecovery} 
                email={this.state.emailRecovery}
                emailChange={this.onRecoveryChange} />
        </div>
    )
}

const mapStateToProps = (state) => {
    return {
       login: state.login,
       recovery: state.recovery,
        submit_recover: state.submit_recover
    }
}

function mapDispatchToProps(dispatch){
    return bindActionCreators({ showLogin,showRecovery,submitRecovery }, dispatch);
}

【问题讨论】:

  • 让 redux 像往常一样将调度分配给您的组件,并从您的非反应代码中调用一个调用调度的方法
  • 感谢@AbderrahmaneTAHRIJOUTI,但我认为上面的 utils.js 已经完成了。如前所述,动作在 app.js 上被分派和接收。问题是如何在从 utils.js 调度该操作时触发 onLoginClick 方法
  • 添加像componentDidMount() {} 这样的生命周期方法,其中包含$("#signin_button").addEventListener('click', this.onLoginClick.bind(this)) 和其他需要的侦听器?
  • @RikkuBölske,完美,可以。我只使用 document.getElementById("signin_button") 更改为纯 js。请把它作为一个答案,以便我可以正确地接受它。非常感谢。
  • @RikkuBölske。这行得通,但我想到触发 onLoginClick() 的不是 Redux 状态的变化,而是点击事件本身。不确定这是否会导致一些竞争条件。

标签: javascript reactjs redux


【解决方案1】:
componentWillReceiveProps(nextProps) {
  this.onLoginClick(nextProps);
}

onLoginClick (nextProps) {
    if (nextProps.login.length > this.props.login.length) {
        this.setState({message: nextProps.login});
        $("#popup_sign").show();
}

【讨论】:

  • 好的,我相信我已经弄清楚了。应该使用的生命周期方法实际上是componentWillReceiveProps(nextProps)。它是捕捉道具变化的地方,也是可以使用 this.setState() 的地方。它看起来像这样:componentWillReceiveProps(nextProps) { this.onLoginClick(nextProps); }。然后`onLoginClick (nextProps) {//do stuff}`。
  • 如果您愿意,请将您的答案调整为以上,以便我接受。你让我走上正轨。谢谢。
  • 不需要componentDidMount。我编辑了您的答案等待审核。
  • 哦。你把const nonReactBtn = document.getElementById("signin_button"); nonReactBtn.addEventListener('click', showLogin); 搬到别的地方了吗?我认为这至少应该反映在答案中(因为最初的问题是关于这个的)
  • 这完全没有必要。当 props 改变时触发 componentWillReceiveProps()。因此,每当用户单击 signin_button 时,都会根据 utils 调度操作。上面的js。然后,当 props 发生变化以反映这一点时,React 会自动触发 componentWillReceiveProps。那是我需要调用 onLoginClick 方法的钩子。我不想在点击事件上附加任何内容,而是在正常的道具更改上附加任何内容。查看文档 [链接] (reactjs.org/docs/react-component.html#componentwillreceiveprops)
猜你喜欢
  • 2022-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-16
相关资源
最近更新 更多