Reactjs Redux Observable和Rxjs不捕获第一个事件,但捕获第二个事件

Reactjs Redux Observable和Rxjs不捕获第一个事件,但捕获第二个事件,reactjs,typescript,redux,rxjs,observable,Reactjs,Typescript,Redux,Rxjs,Observable,我一直在开发一个聊天机器人应用程序,它是用Typescript编写的,使用rxjs的Redux Observable。我试图将一个click事件从Shell.tsx组件发送到我的redux存储,它首先被rxjs Epic截获,然后被发送到redux存储。但是我的redux商店的返回状态不会影响应该在单击事件上进行的更改,但是它会在第二次单击时返回预期结果 这是my Shell.tsx的一部分,它包含相关的组件方法,这些组件方法将click事件作为对存储的操作触发: import * as

我一直在开发一个聊天机器人应用程序,它是用Typescript编写的,使用rxjs的Redux Observable。我试图将一个click事件从Shell.tsx组件发送到我的redux存储,它首先被rxjs Epic截获,然后被发送到redux存储。但是我的redux商店的返回状态不会影响应该在单击事件上进行的更改,但是它会在第二次单击时返回预期结果

这是my Shell.tsx的一部分,它包含相关的组件方法,这些组件方法将click事件作为对存储的操作触发:

    import * as React from 'react';
    import { ChatState, FormatState } from './Store';
    import { User } from 'botframework-directlinejs';
    import { classList } from './Chat';
    import { Dispatch, connect } from 'react-redux';
    import { Strings } from './Strings';
    import { createStore, ChatActions, sendMessage } from './Store';

    import { Subscription } from 'rxjs/Subscription';
    import { Observable } from 'rxjs/Observable';
    import 'rxjs/add/observable/fromEvent';
    import 'rxjs/add/observable/merge';

interface Props {
    inputText: string,
    strings: Strings,
    isActive: boolean,

    onChangeText: (inputText: string) => void,

    sendMessage: (inputText: string) => void
    checkActive: (isChatActive: boolean) => void
}

private handleChatClick(isChatActive) {
        this.store.dispatch({type: 'Chat_Activate', isChatActive: true})
        setTimeout(() => {
            this.store.subscribe(() => {
                this.isActive = this.store.getState().shell.isChatActive
            })
            console.log(this.isActive)
        }, 3000)
        if (this.isActive) {
            this.forceUpdate()
        }
        // this.props.checkActive(true)
    }

render() {

        //other code

        return (
            <div className={ className }>
                <div className="wc-textbox">
                {
                    console.log('chat rendered')
                }
                    <input
                        type="text"
                        className="wc-shellinput"
                        ref={ input => this.textInput = input }
                        value={ this.props.inputText }
                        onChange={ _ => this.props.onChangeText(this.textInput.value) }
                        onKeyPress={ e => this.onKeyPress(e) }
                        placeholder={ placeholder }
                        aria-label={ this.props.inputText ? null : placeholder }
                        aria-live="polite"
                        // onFocus={ this.props.handleChatClick}
                        onClick={() => {
                            this.handleChatClick(true)
                        }}
                    />
                </div>
            </div>
        );
    }


export const Shell = connect(
    (state, ownProps) => {
        return {
            inputText: state.shell.input,
            strings: state.format.strings,
            isActive: state.shell.isChatActive,

            // only used to create helper functions below
            locale: state.format.locale,
            user: state.connection.user
        }
    }
    , {
        // passed down to ShellContainer
        onChangeText: (input: string) => ({ type: 'Update_Input', input, source: "text" } as ChatActions),
        // only used to create helper functions below
        sendMessage
    }, (stateProps: any, dispatchProps: any, ownProps: any): Props => ({
        // from stateProps
        inputText: stateProps.inputText,
        strings: stateProps.strings,
        isActive: stateProps.isActive,
        // from dispatchProps
        onChangeText: dispatchProps.onChangeText,
        checkActive: dispatchProps.checkActive,
        // helper functions
        sendMessage: (text: string) => dispatchProps.sendMessage(text, stateProps.user, stateProps.locale),
    }), {
        withRef: true
    }
)(ShellContainer);
import*as React from'React';
从“/Store”导入{ChatState,FormatState};
从'botframework directlinejs'导入{User};
从“/Chat”导入{classList};
从“react-redux”导入{Dispatch,connect};
从“/Strings”导入{Strings};
从“/Store”导入{createStore、ChatActions、sendMessage};
从'rxjs/Subscription'导入{Subscription};
从“rxjs/Observable”导入{Observable};
导入“rxjs/add/observable/fromEvent”;
导入“rxjs/add/observable/merge”;
界面道具{
输入文本:字符串,
弦:弦,
isActive:布尔值,
onChangeText:(inputText:string)=>void,
sendMessage:(inputText:string)=>void
checkActive:(isChatActive:boolean)=>void
}
专用手柄ChatClick(iChatActive){
this.store.dispatch({type:'Chat_Activate',isChatActive:true})
设置超时(()=>{
this.store.subscribe(()=>{
this.isActive=this.store.getState().shell.isChatActive
})
console.log(this.isActive)
}, 3000)
如果(this.isActive){
这个.forceUpdate()文件
}
//this.props.checkActive(true)
}
render(){
//其他代码
返回(
{
console.log('chat rendered')
}
this.textInput=input}
值={this.props.inputText}
onChange={{{{>this.props.onChangeText(this.textInput.value)}
onKeyPress={e=>this.onKeyPress(e)}
占位符={占位符}
aria标签={this.props.inputText?null:占位符}
aria live=“礼貌”
//onFocus={this.props.handleChatClick}
onClick={()=>{
此.handleChatClick(true)
}}
/>
);
}
export const Shell=connect(
(状态,ownProps)=>{
返回{
inputText:state.shell.input,
字符串:state.format.strings,
isActive:state.shell.isChatActive,
//仅用于创建下面的帮助器函数
语言环境:state.format.locale,
用户:state.connection.user
}
}
, {
//传给贝壳容器
onChangeText:(输入:字符串)=>({type:'Update_input',input,source:'text}作为ChatActions),
//仅用于创建下面的帮助器函数
发送消息
},(stateProps:any,dispatchProps:any,ownProps:any):Props=>({
//来自国家支柱
inputText:stateProps.inputText,
字符串:stateProps.strings,
isActive:stateProps.isActive,
//从调度道具
onChangeText:dispatchProps.onChangeText,
checkActive:dispatchProps.checkActive,
//辅助函数
sendMessage:(text:string)=>dispatchProps.sendMessage(text,stateProps.user,stateProps.locale),
}), {
withRef:true
}
)(贝壳容器);
这是my Store.ts代码的一部分:

export interface ShellState {
    sendTyping: boolean
    input: string,
    isChatActive: boolean,
    isPinging: boolean
}

export const setChatToActive = (isChatActive: boolean) => ({
    type: 'Chat_Activate',
    isChatActive: isChatActive,
    } as ChatActions);

export const ping = (isPinging: boolean) => ({
    type: 'Is_Pinging',
    isPinging: isPinging
} as ChatActions)

export type ShellAction = {
    type: 'Update_Input',
    input: string
    source: "text"
} |  {
    type: 'Card_Action_Clicked'
} | {
    type: 'Set_Send_Typing',
    sendTyping: boolean
} | {
    type: 'Send_Message', 
    activity: Activity
} | {
    type: 'Chat_Activate',
    isChatActive: boolean
} | {
    type: 'Is_Pinging',
    isPinging: boolean
}


export const shell: Reducer<ShellState> = (
    state: ShellState = {
        input: '',
        sendTyping: false,
        isChatActive: false,
        isPinging: false
    },
    action: ShellAction
) => {
    console.log(state)
    switch (action.type) {
        case 'Update_Input':
            return {
                ... state,
                input: action.input
            };
        case 'Send_Message':
            return {
                ... state,
                input: ''
            };
        case 'Chat_Activate':
            const newState = {
                ...state,
                isChatActive: action.isChatActive
            }
            return newState
        case 'Set_Send_Typing':
            return {
                ... state,
                sendTyping: action.sendTyping
            };

        case 'Card_Action_Clicked':
           return {
               ... state
           };
        case 'Is_Pinging':
            const newPing = {
                ... state,
                isPinging: action.isPinging
            }
            return newPing;

        default:
        return state;
    }
}




// 2. Epics 

//************************************************************************
//Import modules
import { applyMiddleware } from 'redux';
import { Epic } from 'redux-observable';
import { Observable } from 'rxjs/Observable';

import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/delay';
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/filter';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/merge';
import 'rxjs/add/operator/mergeMap';
import 'rxjs/add/operator/mapTo';

import 'rxjs/add/operator/throttleTime';
import 'rxjs/add/operator/takeUntil';

import 'rxjs/add/observable/bindCallback';
import 'rxjs/add/observable/empty';
import 'rxjs/add/observable/of';

//************************************************************************
//Asynchronously send messages
const sendMessageEpic: Epic<ChatActions, ChatState> = (action$, store) =>
    action$.ofType('Send_Message')
    .map(action => {
        const state = store.getState();
        const clientActivityId = state.history.clientActivityBase + (state.history.clientActivityCounter - 1);
        return ({ type: 'Send_Message_Try', clientActivityId } as HistoryAction);
    });

const setChatToActiveEpic: Epic<ChatActions, ChatState> = (action$, store) =>
    action$.ofType('Chat_Activate')
    .mapTo({type: 'Chat_Activate', isChatActive: true} as ChatActions)
    .takeUntil(
        action$.ofType('Chat_Activate')
    )

const pingEpic: Epic<ChatActions, ChatState> = (action$, store) => 
    action$.ofType('Is_Pinging')
    .mapTo({type: 'Is_Pinging', isPinging: true} as ChatActions)
    .takeUntil(
        action$.ofType('Is_Pinging')
    )


// 3. Now we put it all together into a store with middleware

import { Store, createStore as reduxCreateStore, combineReducers } from 'redux';
import { combineEpics, createEpicMiddleware } from 'redux-observable';

export const createStore = () =>
    reduxCreateStore(
        combineReducers<ChatState>({
            shell,
            format,
            size,
            connection,
            history      
        }),
        applyMiddleware(createEpicMiddleware(combineEpics(
            updateSelectedActivityEpic,
            sendMessageEpic,
            trySendMessageEpic,
            retrySendMessageEpic,
            showTypingEpic,
            sendTypingEpic,
            setChatToActiveEpic,
            pingEpic
        )))
    );

export type ChatStore = Store<ChatState>;
导出接口外壳状态{
发送类型:布尔
输入:字符串,
isChatActive:布尔值,
isping:布尔值
}
export const setChatToActive=(isChatActive:boolean)=>({
键入:“聊天\激活”,
isChatActive:isChatActive,
}作为行动);
导出常量ping=(isping:boolean)=>({
类型:“正在进行中”,
isping:isping
}(作为行动)
导出类型ShellAction={
键入:“更新输入”,
输入:字符串
资料来源:“文本”
} |  {
键入:“卡片\操作\单击”
} | {
键入:“设置\发送\键入”,
发送类型:布尔
} | {
键入:“发送消息”,
活动:活动
} | {
键入:“聊天\激活”,
isChatActive:布尔值
} | {
类型:“正在进行中”,
isping:布尔值
}
导出常量外壳:减速机=(
状态:ShellState={
输入:“”,
sendTyping:false,
isChatActive:错误,
isPinging:错误
},
行动:炮弹行动
) => {
console.log(状态)
开关(动作类型){
案例“更新输入”:
返回{
……国家,
输入:action.input
};
案例“发送消息”:
返回{
……国家,
输入:“”
};
案例“聊天室激活”:
常数newState={
……国家,
isChatActive:action.isChatActive
}
返回新闻状态
案例“设置\发送\键入”:
返回{
……国家,
sendTyping:action.sendTyping
};
案例“卡片行动点击”:
返回{
…州
};
“正在”案例:
常数newPing={
……国家,
isping:action.isping
}
返回新平;
违约:
返回状态;
}
}
// 2. 史诗
//************************************************************************
//导入模块
从'redux'导入{applyMiddleware};
从'redux observable'导入{Epic};
从rxjs导入{Observable}/
export const shell: Reducer<ShellState> = (
    state: ShellState = {
        input: '',
        sendTyping: false,
        isChatActive: false,
        isPinging: false
    },
    action: ShellAction
) => {
    console.log(state)
// this updates the store
this.store.dispatch({type: 'Chat_Activate', isChatActive: true})
// 3 seconds later, you're listening for store changes, but it's already changed
setTimeout(() => {
    this.store.subscribe(() => {
        this.isActive = this.store.getState().shell.isChatActive
    })
    // then you console.log this.isActive which might be false because that's the initial state in the reducer
    console.log(this.isActive)
}, 3000)
this.store.subscribe(() => {
    this.isActive = this.store.getState().shell.isChatActive;
});
this.store.dispatch({type: 'Chat_Activate', isChatActive: true});
private handleChatClick(isChatActive) {
    console.log(`before click/chat active event: ${this.store.getState().shell.isChatActive}`);
    this.store.dispatch({type: 'Chat_Activate', isChatActive: true})
    console.log(`after click/chat active event: ${this.store.getState().shell.isChatActive}`);
}