Создание Tweet Display Box в ReactJS - PullRequest
0 голосов
/ 17 июня 2019

Я использую следующий код для создания поля ввода Tweet, которое принимает text / video / image / emoji. И они могут быть в разных комбинациях.

Я не уверен, как сгенерировать окно отображения твита, в котором отображается окончательное отображение текста / изображения / смайликов? Я понимаю, что мне может понадобиться поместить разные входные данные в массив или что-то в этом роде, но что после этого. Мой текущий код для отображения стороны ничего не выполняет, и я не уверен, куда идти дальше.

Я ищу окно отображения следующей формы после Submit Button:

enter image description here

Код components/EmojiPicker.js имеет:

import React, {useState} from 'react'
import ReactDOM from "react-dom";
import { Picker } from "emoji-mart";
import Button from "@material-ui/core/Button";

const EmojiPicker = ({ onSelect }) => {
    const [show, setShow] = useState(false);
    return (
      <>
        <Button
          onClick={() => setShow(oldState => !oldState)}
          style={{ width: "30px", height: "30px", borderRadius: "4px", border: "3px solid", display: "flex", alignItems: "center", justifyContent: "center",
            background: "transparent"}}>
          ej
        </Button>
        {ReactDOM.createPortal(
          show && <Picker onSelect={onSelect} />,
          document.body
        )}
      </>
    );
  };

  export default EmojiPicker

Код components/FileInput.js имеет:

import React, {useRef} from 'react'

const FileInput = ({ onChange, children }) => {
    const fileRef = useRef();
    const onPickFile = event => {
      onChange([...event.target.files]);
    };
    return (
      <div
        style={{
          width: "35px",
          height: "35px",
          borderRadius: "3px"
        }}
        onClick={() => fileRef.current.click()}
      >
        {children}
        <input
          multiple
          ref={fileRef}
          onChange={onPickFile}
          type="file"
          style={{ visibility: "hidden" }}
        />
      </div>
    );
  };

  export default  FileInput

Компоненты кода / tweetboxImgInp.js как:

import React, {useState, useEffect} from 'react'


const ImgIcon = () => (
    <svg focusable="false" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
      <path d="M0 0h24v24H0z" fill="none" />
      <path d="M14 13l4 5H6l4-4 1.79 1.78L14 13zm-6.01-2.99A2 2 0 0 0 8 6a2 2 0 0 0-.01 4.01zM22 5v14a3 3 0 0 1-3 2.99H5c-1.64 0-3-1.36-3-3V5c0-1.64 1.36-3 3-3h14c1.65 0 3 1.36 3 3zm-2.01 0a1 1 0 0 0-1-1H5a1 1 0 0 0-1 1v14a1 1 0 0 0 1 1h7v-.01h7a1 1 0 0 0 1-1V5z" />
    </svg>
  );

  export const Img = ({ file, onRemove, index }) => {
    const [fileUrl, setFileUrl] = useState(null);
    useEffect(() => {
      if (file) {
        setFileUrl(URL.createObjectURL(file));
      }
    }, [file]);

    return fileUrl ? (
      <div style={{ position: "relative", maxWidth: "230px", maxHeight: "95px" }}>
        <img
          style={{
            display: "block",
            maxWidth: "230px",
            maxHeight: "95px",
            width: "auto",
            height: "auto"
          }}
          alt="pic"
          src={fileUrl}
        />
        <div
          onClick={() => onRemove(index)}
          style={{
            position: "absolute",
            right: 0,
            top: 0,
            width: "20px",
            height: "20px",
            borderRadius: "50%",
            background: "black",
            color: "white",
            display: "flex",
            alignItems: "center",
            justifyContent: "center"
          }}
        >
          x
        </div>
      </div>
    ) : null;
  };

  export default ImgIcon

А App.js имеет:

import React, { useRef, useState } from "react";
import ImgIcon, {Img} from './components/tweetboxImgInp'
import EmojiPicker from './components/EmojiPicker'
import FileInput from './components/FileInput'
import "emoji-mart/css/emoji-mart.css";
import "./styles.css";

function App() {
  const [text, setText] = useState("");
  const [pics, setPics] = useState([]);
  const textAreaRef = useRef();
  const insertAtPos = value => {
    const { current: taRef } = textAreaRef;
    let startPos = taRef.selectionStart;
    let endPos = taRef.selectionEnd;
    taRef.value =
      taRef.value.substring(0, startPos) +
      value.native +
      taRef.value.substring(endPos, taRef.value.length);
  };
  return (
    <div style={{display: "flex", flexDirection: "column", border: "3px solid", borderRadius: "5px", width: "600px", minHeight: "200px", padding: "20px"}}    >
      <div style={{ display: "flex", flexDirection: "column", flex: 1, border: "1px solid", borderRadius: "5px", margin: "0px"}}>
        <textarea
          ref={textAreaRef}
          value={text}
          style={{ flex: 1, border: "none", minHeight: "150px" }}
          onChange={e => setText(e.target.value)}
        />
        <div style={{ display: "flex", flexDirection: "row", flexWrap: "wrap", background: "fbfbfb"}} >
          {pics.map((picFile, index) => (
            <Img key={index} index={index} file={picFile} onRemove={rmIndx =>
                setPics(pics.filter((pic, index) => index !== rmIndx))}/>))}
        </div>
      </div>
      <div style={{ display: "flex", flexDirection: "row", alignItems: "center", marginTop: "20px" }}>
        <div style={{ marginRight: "20px" }}>
          <FileInput onChange={pics => setPics(pics)}>
            {/* <ImgIcon /> */}
            Tes
          </FileInput>
        </div>
        <EmojiPicker onSelect={insertAtPos} />
      </div>
    </div>
  );
}

export default App

Редактировать: у меня все в порядке с дисплеем, принимающим только 1 медиафайл, текст и несколько смайликов. Меня удивит, если я в 2019 году буду единственным, кто хочет сделать это ради удовольствия.

1 Ответ

1 голос
/ 21 июня 2019

Рабочий пример

Нажмите кнопку кодов и коробки для просмотра демо

Edit competent-currying-u59b5

Компонент отображения твита довольно прост. Это колонка flexbox с двумя частями. Первая часть колонки содержит твит. Вторая часть столбца содержит список изображений / медиа элементов. Emoji является частью текстового компонента.


enter image description here


Tweet Display Component

const Tweet = ({ tweet: { text, images } }) => (
  <div
    style={{
      margin: "20px",
      border: "1px solid grey",
      width: "600px",
      padding: "20px",
      borderRadius: "3px"
    }}
  >
    <div>{text}</div>
    {images.length > 0 && (
      <div
        style={{
          display: "flex",
          flexDirection: "row",
          flexWrap: "wrap",
          background: "fbfbfb",
          padding: "30px 0"
        }}
      >
        {images.map((img, i) => (
          <Img key={i} file={img} index={i} isSingle={images.length === 1} />
        ))}
      </div>
    )}
  </div>
);

Для получения дополнительной информации о покупке эта статья css-tricks , чтобы получить больше информации о css flex layout

...