【问题标题】:Inserting HTML into a Snackbar message将 HTML 插入到 Snackbar 消息中
【发布时间】:2021-03-03 07:34:32
【问题描述】:

所以我要分叉一个示例 Twilio 视频聊天应用程序 (https://github.com/twilio/twilio-video-app-react)。对于聊天功能,使用了 Snackbar 消息。哪个工作正常。但我想允许用户发送以 http 开头的消息,这样该消息将作为超链接 URL 发送。

ChatInput 组件可以很好地将此消息显示为本地用户(即发件人)的超链接 URL。但远程用户的 DataTrack 事件处理程序不会将消息显示为超链接。只显示文字。

这里是 ChatInput.tsx,任何以 http 开头的消息都会正确显示给本地用户。

import React, { useState } from 'react';
import { Button, FormControl, TextField } from '@material-ui/core';
import { useSnackbar } from 'notistack';
import useVideoContext from '../../../hooks/useVideoContext/useVideoContext';

export default function ChatInput() {
  const [message, setMessage] = useState('');
  const { room } = useVideoContext();
  const { enqueueSnackbar } = useSnackbar();

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => setMessage(e.target.value);

  const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();

    if (message) {
      // Get the LocalDataTrack that we published to the room.
      const [localDataTrackPublication] = [...room.localParticipant.dataTracks.values()];

      // Construct a message to send
      const fullMessage = `${room.localParticipant.identity} says: ${message}`;

      if (message.startsWith('http')) {
        // Send the message
        localDataTrackPublication.track.send(`<a href="${message}">${message}</a>`);

        // Render the message locally so the local participant can see that their message was sent.
        enqueueSnackbar(<a href={message}>{message}</a>);
      } else {
        // Send the full message
        localDataTrackPublication.track.send(fullMessage);

        // Render the full message locally so the local participant can see that their message was sent.
        enqueueSnackbar(fullMessage);
      }
      //Reset the text field
      setMessage('');
    }
  };

  return (
    <form autoComplete="off" style={{ display: 'flex', alignItems: 'center' }} onSubmit={handleSubmit}>
      <FormControl>
        <label htmlFor="chat-snack-input" style={{ color: 'black' }}>
          Say something:
        </label>
        <TextField value={message} autoFocus={true} onChange={handleChange} id="chat-snack-input" size="small" />
      </FormControl>
      <Button type="submit" color="primary" variant="contained" style={{ marginLeft: '0.8em' }}>
        Send
      </Button>
    </form>
  );
}

这里是 DataTrack.ts,它只显示任何远程用户的字符串文字。

import { useEffect } from 'react';
import { DataTrack as IDataTrack } from 'twilio-video';
import { useSnackbar } from 'notistack';

var stringToHTML = function (str) {
    var parser = new DOMParser();
    var doc = parser.parseFromString(str, 'text/html');
    return doc.body;
};

export default function DataTrack({ track }: { track: IDataTrack }) {
  const { enqueueSnackbar } = useSnackbar();

  useEffect(() => {
    const handleMessage = (message: string) => { 
    if (message.startsWith('http')) {
        const newMessage = stringToHTML(message);
        enqueueSnackbar(newMessage);
        }
    else {
    enqueueSnackbar(message); }
    };
    track.on('message', handleMessage);
    return () => {
      track.off('message', handleMessage);
    };
  }, [track, enqueueSnackbar]);

  return null; // This component does not return any HTML, so we will return 'null' instead.
}

关于如何让远程用户接收与发件人看到的相同超链接 URL 的任何建议?

【问题讨论】:

    标签: reactjs snackbar twilio-video


    【解决方案1】:

    TL;DR:函数stringToHTML在将消息传递给NotiStack时返回一个DOM元素引用而不是React元素,尝试用React元素包装它:

    //const newMessage = stringToHTML(message);
    enqueueSnackbar(<div dangerouslySetInnerHTML={{__html:message}} />);
    

    NL;PR: 和/或我不确定为什么您在两个组件中将消息值传递给 NotiStack 的方式不同:

    if (message.startsWith('http')) { 
    //local user
     enqueueSnackbar(<a href={message}>{message}</a>); //1)
    //vs.  remote user
    const newMessage = stringToHTML(message);
    enqueueSnackbar(newMessage); // should it be the same as 1)?
    

    【讨论】:

      【解决方案2】:

      感谢您的反馈。我以两种不同的方式处理消息,具体取决于是否传递了 URL。实际上,项目作者实际上提供了一个干净的解决方案。安装 Linkify 包只允许那些被推断为 HTML 的字符串元素被格式化。

      这是重做的 DataTrack.tsx 内容。像冠军一样工作!

      import React from 'react';
      import { useEffect } from 'react';
      import { DataTrack as IDataTrack } from 'twilio-video';
      import { useSnackbar } from 'notistack';
      
      import Linkify from 'react-linkify';
      
      export default function DataTrack({ track }: { track: IDataTrack }) {
        const { enqueueSnackbar } = useSnackbar();
        useEffect(() => {
          const handleMessage = (message: string) =>
            enqueueSnackbar(
              <Linkify
                componentDecorator={(decoratedHref, decoratedText, key) => (
                  <a target="_blank" rel="noopener" href={decoratedHref} key={key}>
                    {decoratedText}
                  </a>
                )}
              >
                {message}
              </Linkify>
            );
          track.on('message', handleMessage);
          return () => {
            track.off('message', handleMessage);
          };
        }, [track, enqueueSnackbar]);
      
        return null; // This component does not return any HTML, so we will return 'null' instead.
      }

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-03-30
        • 1970-01-01
        • 1970-01-01
        • 2013-04-05
        • 2019-12-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多