проблема с отправкой тэгов на сервер в React
Сделал виджет тэгов, чтоб выделял их отдельными объектами, но теперь столкнулся с проблемой, что сервер не принимает эти тэги. Код Модального окна, где реализованы тэги:
import React, {useRef, useEffect, useCallback, useState} from 'react'
import { Link } from 'react-router-dom'
import {useSpring, animated} from 'react-spring'
import styled from 'styled-components'
import {MdClose} from 'react-icons/md'
// import modalImg from './modal.jpg'
import './Modal.scss';
import TagsInput from './components/TagsInput'
export const Modal = ({showModal, setShowModal}) => {
const modalRef = useRef()
const [validate, setValidate] = useState(false)
const [tags, setTags] = useState([]);
const [errors, setErrors] = useState({});
const changeHandler = (name, value) => {
if(name === 'tags') {
setTags(value);
if(value.length > 0 && errors.tags) {
setErrors(prev => {
const prevErrors = {...prev};
delete prevErrors.tags;
return prevErrors;
});
}
}
}
const submitHandler = e => {
e.preventDefault();
if(tags.length === 0) {
setErrors(prev => ({
...prev,
tags: 'Please add at least one tag'
}));
}
if(tags.length > 0 ) {
console.log(tags);
// Submit form
}
}
const animation = useSpring({
config: {
duration: 250
},
opacity: showModal ? 1 : 0,
transform: showModal ? `translateY(0%)` : `translateY(-100%)`
})
const closeModal = e => {
if(modalRef.current === e.target){
setShowModal(false)
}
}
const keyPress = useCallback(e =>{
if(e.key === 'Escape' && showModal){
setShowModal(false)
}
}, [setShowModal, showModal])
useEffect(()=>{
document.addEventListener('keydown', keyPress)
return () => document.removeEventListener('keydown', keyPress)
}, [keyPress])
return(
<>
{ showModal ? (
<Background ref={modalRef} onClick={closeModal}>
<animated.div style={animation}>
<ModalWrapper showModal={showModal}>
<ModalImg>
<div className="ModalLeft">
<form action="/api/videos/upload" method="post" enctype="multipart/form-data">
<div className="download-form">
<input type="file" name="filedata" />
<input type="text" name="videoname" className="form-control" placeholder="Название вашего видео" required/>
<TagsInput
label="Tags"
type="text"
id="tags"
name="tags"
placeholder="Укажите тэги"
onChange={changeHandler}
error={errors.tags}
defaultTags={tags}
/>
<input type="submit" className="btnS" value="Загрузить"/>
</div>
</form>
</div>
</ModalImg>
<ModalContent>
<h2>Скорее нажмите на кнопку Загрузить!</h2>
<p>Загружая видео, вы принимаете нашу политику конфиденциальности</p>
</ModalContent>
<CloseModalButton
aria-label='Close modal'
onClick={()=> setShowModal (prev => !prev)}
/>
</ModalWrapper>
</animated.div>
</Background>
): null}
</>
)
}
Код реализации компонента тэгов:
import React, { useState } from 'react';
import { validateEmail } from '../helpers/validate';
const TagsInput = ({ label, id, name, placeholder, error, onChange, defaultTags, emailValidation }) => {
const [value, setValue] = useState('');
const [tags, setTags] = useState(defaultTags ? defaultTags : []);
const [isActive, setIsActive] = useState(false);
const changeHandler = (e) => {
setValue(e.target.value);
onChange(name, tags);
}
const removeTag = (tag) => {
const arr = tags.filter(t => t !== tag);
setTags(arr);
onChange(name, arr);
}
const updateTagsHandler = (e) => {
e.preventDefault();
// Add tags if input is not empty and if input value is not comma
if(e.target.value !== '' && e.target.value !== ',') {
if(e.key === ',') {
const newTag = value.trim().split(',')[0];
if(emailValidation) {
if(!tags.includes(newTag) && newTag !== '' && validateEmail(newTag)) {
const arr = [...tags, newTag];
setTags(arr);
onChange(name, arr);
}
}else {
if(!tags.includes(newTag) && newTag !== '') {
const arr = [...tags, newTag];
setTags(arr);
onChange(name, arr);
}
}
setValue('');
} else if(e.key === 'Enter') {
const newTag = value.trim();
if(emailValidation) {
if(!tags.includes(newTag) && newTag !== '' && validateEmail(newTag)) {
const arr = [...tags, newTag];
setTags(arr);
onChange(name, arr);
}
}else {
if(!tags.includes(newTag) && newTag !== '') {
const arr = [...tags, newTag];
setTags(arr);
onChange(name, arr);
}
}
setValue('');
}
}
// Remove tags if backspace is pressed
if(e.key === 'Backspace' && tags.length > 0) {
const copyOfTags = [...tags];
copyOfTags.pop();
setTags(copyOfTags);
onChange(name, copyOfTags);
}
}
const focusHandler = () => {
setIsActive(true);
}
const blurHandler = () => {
setIsActive(false);
}
return(
<div className={!isActive ? "tags-input" : "tags-input active"}>
{label && <label htmlFor={id ? id : name}>{label}</label>}
<div className="tags-input__wrapper">
<div className="tags-input__tags">
{tags.map((tag, i) =>
<div key={i} className="tag">
{tag} <span onClick={() => removeTag(tag)}><i className="fa fa-times-circle"></i></span>
</div>
)}
<input
type="text"
placeholder={placeholder}
name={name}
id={id ? id : name}
value={value}
onChange={changeHandler}
autoComplete="off"
onKeyUp={updateTagsHandler}
onKeyDown={(e) => e.key === 'Enter' && e.preventDefault()}
onKeyPress={(e) => e.key === 'Enter' && e.preventDefault()}
onFocus={focusHandler}
onBlur={blurHandler}
/>
</div>
</div>
{error && <div className="error">{error}</div>}
</div>
);
}
export default TagsInput;
Код fetcha на сервер
if (!req.file) {
reject({"Error": "Invalid filetype!"});
return;
}
let fileinfo = req.file;
if(req.body.videoname && req.body.tags && req.session.passport.user){
fileinfo.videoname = req.body.videoname;
fileinfo.tags = [req.body.tags];
fileinfo.userID = req.session.passport.user;
const author = await authAPI.getUser({_id: req.session.passport.user});
fileinfo.channelName = author.nickname;
}
else{
reject("Video must have a name and tags")
return;
}