Textarea problem that I use inside a map using React

Asked

Viewed 28 times

1

I don’t have much experience with reactjs, but I’m doing a project that uses this lib, using typescript as a language. The problem is this, even before I used a map to render the elements of an array on screen was working, from the moment I inserted the map with the array I started having the following problem, when I type in a textarea all are triggered at the same time and have the same content and I still can’t save the contents follows the code...

import React, { ChangeEvent, FormEvent, useState, useEffect } from 'react';
import api from '../../../../../services/api';
import { TComent, TPost } from '../../../../../utils/types/types';

import Panel from '../../Panel';

import {
  Container,
  Row,
  PostImage,
  Separator,
  Avatar,
  Column,
  LikeIcon,
  CommentIcon,
  ShareIcon,
  SendIcon,
} from './styles';

const FeedPost: React.FC = () => {

  const [contentFeedPost, setContentFeedPost] = useState<TPost[]>([])
  const [formData, setFormData] = useState({
    contents: ''
  })

  useEffect(() => {
    api.get<TPost[]>('groups_page/posts/1').then(response => {
      setContentFeedPost(response.data)
    })
  },[])

  async function handleSubmit(event: FormEvent) {
    event.preventDefault()

    const {
      contents
    } = formData

    setFormData({
      contents: ""
    })

    const data = {
      contents
    }

    await api.post('groups_page/coments/1/1', data)

  }

  function handleTextAreaChange(event: ChangeEvent<HTMLTextAreaElement>) {

    const { name, value } = event.target

    setFormData({
      ...formData,
      [name]: value
    })

  }

  return (
    <form onSubmit={handleSubmit} >
      {contentFeedPost.map((post) => (

        <>
          <Panel>
            <Container>
              <Row className="heading">
                <Avatar src={post.user.image_url} alt="Member" />
                <Column>
                  <h3>{post.user.name}</h3>
                  <h4>Engenharia de Computação</h4>
                  <time>{post.date}</time>
                </Column>
              </Row>

              <Row>
                <Separator />
              </Row>

              <Row>
                <p>
                  {post.contents}
                </p>
              </Row>

              <Row>
                <Separator />
              </Row>

              {post.attachment
                ?
                <PostImage
                  src={post.attachment.url}
                  alt="Attachment"
                />
                : null
              }

              <Row className="likes">
                <span className="circle blue" />
                <span className="circle green" />
                <span className="circle red" />
                <span className="number">49</span>
              </Row>

              <Row>
                <Separator />
              </Row>

              <Row className="actions">
                <button>
                  <LikeIcon />
                  <span>Gostei</span>
                </button>
                <button>
                  <CommentIcon />
                  <span>Comentar</span>
                </button>
                <button>
                  <ShareIcon />
                  <span>Compartilhar</span>
                </button>
                <button>
                  <SendIcon />
                  <span>Enviar</span>
                </button>
              </Row>

              <Row>
                <Separator />
              </Row>

              <Row>
                <Avatar src="https://github.com/fsluizvictor.png" alt="Rocketseat" />
                <textarea
                  id={String(post.id)}
                  name="contents"
                  placeholder="Insira um comentário..."
                  value={formData.contents}
                  onChange={handleTextAreaChange}
                />
                <button>
                  <SendIcon />
                </button>
              </Row>

              <Row>
                <Separator />
              </Row>

              {post.coments.map((coment: TComent) => {
                <Row className="coment">
                  <Avatar src={coment.user.image_url} alt="Member" />
                  <Column>
                    <h3>{coment.user.name}</h3>
                    <h4>Engenharia de Computação</h4>
                    <time>{coment.date}</time>
                  </Column>
                  <p>{coment.contents}</p>
                </Row>
              })}

              <Row>
                <Separator />
              </Row>

            </Container>
          </Panel>
        </>
      ))}
    </form>
  );
};

export default FeedPost;```

1 answer

0


What needs to be done to have states independent of textareas?

To be able to edit each post individually it is necessary to each have its own state.

One way to do this is by representing an array within useState

Each array item will be an object with a Contents property.

Initialization: const [formData, setFormData] = useState([])

Creation of items:

 useEffect(() => {
    api.get<TPost[]>('groups_page/posts/1').then(response => {
      setContentFeedPost(response.data)
      setFormData(response.data.map(() => ({content:''})))
    })
  },[])

handleTextAreaChange:

 const handleTextAreaChange = (postIndex: number) => (event: ChangeEvent<HTMLTextAreaElement>) => {

    const { name, value } = event.target

    setFormData(
      formData.map(
         (postData, i) => i !=== postIndex 
             ? postData
             : {...postData, [name]: value}
    ))
  }

map of contentFeedPost: { contentFeedPost.map((post, i) => (

use in textarea:

 <textarea
   id={String(post.id)}
   name="contents"
   placeholder="Insira um comentário..."
   value={formData[i].contents}
   onChange={handleTextAreaChange(i)}
 />

Browser other questions tagged

You are not signed in. Login or sign up in order to post.