Hooks和Redux / useEffect聊天机器人

时间:2020-02-04 21:53:45

标签: reactjs redux

你好,我有一个问题,我处于隐藏聊天状态的输入动画的状态 但由于某种原因,当状态为true时,动画会在所有消息上显示

操作:

     //action user send message
    export const sendMessage = text => ({
      type: ON_MESSAGE,
      text,
    });
//action user wait bot response
    export const wait_anwser = () => ({
      type: WAIT_AWNSER,
    });
//action bot send response
    export const botMessage = text => ({
      type: BOT_MESSAGE,
      text,
    });
//action end wait response   
    export const wait_end = () => ({
      type: WAIT_END
    });

    export const checkMessage = text => {
      return dispatch => {
        dispatch(sendMessage(text));
        dispatch(wait_anwser());
        dispatch(botMessage(verify(text)));
      };
    };

redux:

const initalState = {
  messages: [],
  waitResponse: false,
  bot: false,
};

const messageReducer = (state = initalState, action) => {
  switch (action.type) {
    case ON_MESSAGE:
      return {
        ...state,
        messages: [
          ...state.messages,
          {
            type: 'user',
            text: action.text,
            date: moment().format('DD/MM/YYYY-h:mm:ss'),
          },
        ],
      };

    case BOT_MESSAGE:
      return {
        ...state,
        messages: [
          ...state.messages,
          {
            type: 'bot',
            text: action.text,
            date: moment().format('DD/MM/YYYY-h:mm:ss'),
          },
        ],
      };
    case WAIT_AWNSER:
      return {
        ...state,
        waitResponse: true,
      };
    case WAIT_END: 
    return {
      ...state,
      waitResponse: false,
    };
    default:
      return state;
  }

jsx:

const Chat = props => {
  //Redux
  const dispatch = useDispatch();
  const ChatReducer = useSelector(state => state.Chat);
  const WidgetReducer = useSelector(state => state.WidgetStatus.widgetStatus);
  const [isTyping, setIsTyping] = useState(false);
  const [visibleText, setVisibleText] = useState(['']);

  useEffect(() => {
    if(ChatReducer.waitResponse === true){
      setIsTyping(true);
    }
    const timeoutId = setTimeout(() => {
      setIsTyping(false);
      dispatch(wait_end());
    }, 3000);
    return () => clearTimeout(timeoutId);
  }, [ChatReducer.waitResponse]);

 return (
 <Styled.ChatBox widget={WidgetReducer}>
 <Styled.ChatLog>
         /*here map my state messages*/
        {ChatReducer.messages.map((rowData, index) =>
        /*here is the user messages*/
          rowData.type === 'user' ? (
            <Styled.MessageFlexColumn key={index}>
              <Styled.MessageWrapper user={true}>
                <Styled.ChatMessage user={true}>
                  {rowData.text}
                </Styled.ChatMessage>
              </Styled.MessageWrapper>
              <Styled.Status />
            </Styled.MessageFlexColumn>
          ) : (
          /*here is the bot messages*/
            <Styled.MessageFlexColumn key={index}>
              <Styled.MessageWrapper>
              <Styled.BotImg src={BotLogo} />
                <Styled.ChatMessage>
                <Styled.TypingWrapper show={isTyping}>
                <span></span>
                <span></span>
                <span></span>
              </Styled.TypingWrapper>
              {!isTyping ? rowData.text: ''}
              </Styled.ChatMessage>
              </Styled.MessageWrapper>
              <Styled.Status />
            </Styled.MessageFlexColumn>
          )
        )}
        <div ref={messagesEndRef} />
      </Styled.ChatLog>
 <Styled.ChatBox />

礼物问题:

enter image description here

基本上,所有消息在发送新消息时都具有键入动画 我不知道这段代码是否具有最好的逻辑,基本上我有一个动作可以发送用户消息,以在聊天消息中显示一个wait_response动作,我将在该动作中进行聊天机器人的响应处理

1 个答案:

答案 0 :(得分:0)

我认为您的bot组件中需要这样的东西

const [hasResponded, setHasResponded] = useState(false);


 useEffect(() => {
    // Notice the change here checking if we have already responded
    // The if statement now surrounds the timeout and the interval
    // This prevents any of these actions from happening once the response  has been made
    if(ChatReducer.waitResponse === true && !hasResponded){ 
      setIsTyping(true);
    const timeoutId = setTimeout(() => {have already responded
        setIsTyping(false);
        setHasResponded(true); // flag that this component has responded and need not perform these actions again
        dispatch(wait_end());
      }, 3000);
    }
    return () => clearTimeout(timeoutId);
  }, [ChatReducer.waitResponse, hasResponded]);