Хуки и Redux / useEffect chatbot - PullRequest
0 голосов
/ 05 февраля 2020

Здравствуйте, у меня есть проблема. У меня есть состояние, которое я использую, чтобы скрыть анимацию ввода в чате, но по какой-то причине анимация захватывает все сообщения, когда состояние истинно

действие :

     //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)));
      };
    };

приращение:

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

в основном все сообщения имеют анимацию ввода при отправке нового сообщения. Я не знаю, был ли у меня лучший лог c с этим кодом, в основном у меня есть действие отправить сообщение пользователя для отображения в сообщении чата действия wait_response, в котором я выполняю обработку ответов этого бота чата

1 Ответ

0 голосов
/ 05 февраля 2020

Я думаю, вам нужно что-то подобное в компоненте бота

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]);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...