开发者

(ReactJS) Why do changes made in a component by its event handlers remain when the component is re-rendered?

I'm having a problem in React where if an event handler is triggered in a component, and it changes parts of the component (like style or textContent), those changes don't reset/revert when the component is re-rendered.

More specifics: I want to set up a basic forum/board page where you select a category from one drop down, and then select a topic from the second drop-down. Choosing the topic will fill an array with "post" objects, and the array is used to render the list of posts for it below. There's a search bar at the top which also renders posts through an array of post objects if it finds matches.

The posts that get rendered feature thumbs-up, thumbs-down and trash can icons. The thumbs icons increase/decrease have an onClick event that changes a "likes: " text on that post, while the trash can icon "deletes" the post (changes its display to none; only for visual effect).

The problem is, if I increase the likes/dislikes on a post or "delete" it and change to another topic in the drop-down (or search a term whose post results includes the post I modified or it occupies the same position), the new post that occupies the position on the page of that post that I liked or deleted shows the same likes count (or is missing as if I deleted it).

I tried:

import React, { useEffect, useState } from 'react';
import './CenterColumn.css';
import Post from '../PostComponent/Post.jsx';

function CenterColumn(props) {
  const [topics, setTopics] = useState([]);
  const [posts, setPosts] = useState([]);
  const [topicVal, setTopicVal] = useState("");
  const [categoryVal, setCategoryVal] = useState(0);
  const [reSearch, setReSearch] = useState(false);

  useEffect(function(){
    setCategoryVal("");
    setPosts([]);
    setTopicVal("");
    setTopics([]);
    if (props.searchQuery !== ""){
        let allPosts = [];
        function getAllPosts(){
          let returnArray = [];
          for (let i = 0; i < props.threads.length; i++){
            for (let j = 0; j < props.threads[i].topicList.length; j++){
              for(let k = 0; k < props.threads[i].topicList[j].listPosts.length; k++){
                returnArray.push(props.threads[i].topicList[j].listPosts[k]);
              }
            }
          }

          return returnArray;
        }

        allPosts = getAllPosts();

        let searchResults = allPosts.filter(findResults);

        function findResults(eachPost){
          return (eachP开发者_StackOverflowost.text.toUpperCase().indexOf(props.searchQuery.toUpperCase()) > -1);
        }
        setPosts(searchResults);
        setReSearch(!reSearch);
    }

    else{
      setPosts([]);
    }
  }, [props.renderSwitch]);

  function assignTopics(e){
    setCategoryVal(parseInt(e.target.value));
    setPosts([]);
    setTopicVal("");

    setTopics(function(){
      if (e.target.value !== ""){
        return props.threads[(parseInt(e.target.value) - 1)].topicList;
      }
      
      return [];
    });
  }

  function assignPosts(e){
    setTopicVal(e.target.value);
    setPosts(function(){
      if (e.target.value !== ""){
        return props.threads[categoryVal - 1].topicList[(parseInt(e.target.value) -1)].listPosts;
      }

      return [];
    })
  }

  return ( 
        <section id="centerColumn">
              <section id="dropDownSection">
                <section id="categoryPair">
                    <label htmlFor="categoryDropDown">Choose Category</label>
                    <select id="categoryDropDown" onChange={assignTopics} value={categoryVal}>
                      <option value="">Select a Category</option>
                      {
                          props.threads.map(function(category){
                            return (<option value={category.id} key={category.id}>{category.name}</option>)
                      })}
                    </select>
                </section>
                <section id="topicPair">
                    <label htmlFor="topicDropDown">Choose Topic</label>
                    <select id="topicDropDown" onChange={assignPosts} value={topicVal}>
                      <option value="">Select a Thread</option>
                      {
                          topics.map(function(topic){
                            return (<option value={topic.id} key={topic.id}>{topic.topic_title}</option>)
                      })}
                    </select>
                </section>
              </section>
              <section id="postSection">
                {
                  posts.map(function(post){
                    return (<Post post={post} reSearch={reSearch} />)
                })}
              </section>
        </section>
    );
  }
  
  export default CenterColumn;
import React from 'react';
import {useState, useRef} from 'react';
import './Post.css';
import {FaThumbsUp, FaThumbsDown, FaTrashAlt} from 'react-icons/fa';

function Post(props){
    let likeCounterRef = useRef(null);
    let deleteRef = useRef(null);

    function updateLikes(e){
        if (e.currentTarget.className === "thumbsUp"){
            let likesCount = parseInt(likeCounterRef.current.textContent.split(":")[1]);
            likesCount++;
            likeCounterRef.current.textContent= `likes:${likesCount}`;
            
        }
        else if (e.currentTarget.className === "thumbsDown"){
            let likesCount = parseInt(likeCounterRef.current.textContent.split(":")[1]);
            likesCount--;
            likeCounterRef.current.textContent = `likes:${likesCount}`;
        }
    }


    function deletePost(e){
        deleteRef.current.style.display="none";
    }


    return (
        <section className="wholePost" key={props.post.id} ref={deleteRef}>
            <section className="messageArea">
                <p className="message">{props.post.text}</p><p className="likes" ref={likeCounterRef}>likes:{props.post.like}</p><p className="thumbsUp" onClick={updateLikes}><FaThumbsUp style={{color: "green"}} /></p><p className="thumbsDown" onClick={updateLikes}><FaThumbsDown style={{color: "red"}} /></p>
            </section>
            <section className="metadata">
            <p className="author">by:{props.post.author}</p><p className="postDate">{props.post.date}</p><p className="replies">replies:{props.post.replies}</p><p className="trashCan"><FaTrashAlt style ={{cursor: "pointer"}} onClick={deletePost} /></p>
            </section>
        </section>
    );
}

export default Post;

Expected: The Post component would be completely re-rendered and the text reset/reverted whenever a different drop-down option is selected (or search term is entered that yields a post in the same position as the modified one). The likes count would reset and deleted posts would reappear.

Instead: Changes to the likes count on a post carry over to whichever post newly occupies its position. Similarly, if I "delete" a post and change topic, that new topic's post in the same position/order will also be missing.

Outline of images:

1 - First topic. Didn't click on any likes yet. Likes is at 0:

Topic 1, Likes 0 here

2 - Switched to second topic. Didn't click on any likes yet. Likes is at 22

Topic 2, Likes 22 here

3 - Switched back to first topic. Clicked the thumbs up on the first post. Likes is at 1.

Back to topic 1, clicked thumbs up and likes is now 1

4 - Switched back to second topic. Look at the likes, it went from 22 to 1.

enter image description here

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜