0
const SiteDetails = ({site, user}) => {
  const dispatch = useDispatch()

  const updateSite = async (siteId, siteObject) => {
    try {
      const updatedSite = await siteService.update(siteId, siteObject)
      dispatch(toggleStatus(siteId, updatedSite))
      // dispatch(setNotification(`One like added to ${updatedSite.title}`))
    } catch (exception) {
      console.log(exception)
      dispatch(setNotification("Could not update site"))
    }
  }


  return (
    <div className='site-details'>
      <Link href={site.url}>{site.url}</Link>
      <h2>
        <LikeButton user={user} site={site} updateSite={updateSite} />
        <VisitButton user={user} site={site} updateSite={updateSite} />
      </h2>
      <p>{site.description}</p>
      <img src={site.imageUrl} alt={"Image could not be loaded"} />
    </div>
  )
}

const LikeButton = ({user, site, updateSite}) => {

  const dispatch = useDispatch()
  const likedList = site?.userLiked.find(n => n?.username === user.username)
  useEffect(() => {
    if (!likedList) {
      const newUser = { username: user.username, liked: false }
      const updatedArray = site.userLiked.concat(newUser)
      const updatedSite = {...site, userLiked: updatedArray}
      updateSite(site.id, updatedSite)
    }  
  },[])


  const liked = likedList?.liked

  const handleLike = async () => {
    const indexCurr = site.userLiked.indexOf(likedList)
    //updatedSite is the parent site. This will have its liked status toggled
    //actually updatedUserLiked can simply use username: user.username and liked: true
    const updatedUserLiked = { username: likedList?.username, liked: !likedList.liked}
    site.userLiked[indexCurr] = updatedUserLiked
    const updatedSite = {...site, userLiked: site.userLiked}    
    updateSite(site.id, updatedSite)
    //childSite is the spawned from the parent, 
    //it will contain a parent, which is the updatedSite
    const childSite = {...site, parent: updatedSite, opcode: 100}
    const newSite = await siteService.create(childSite)
    // dispatch(createSite(newSite))
    dispatch(initializeUsers())
    dispatch(initSites())
  }


  return (
    <Button 
      size='small' variant='contained' 
      color={liked ? 'secondary' : 'primary'} 
      onClick={!liked ? handleLike : null} className='site-like'>{liked ? 'Already Liked' : "like"}
    </Button>
  )
}

Expected Behaviour Expected Behaviour

Actual Behaviour Actual Behaviour

Hi everyone, my goal is to make it such that when the 'Like' button is clicked, the appearance of the button will change but the rest of the page does not refresh. However, if you look at the actual behaviour, after the button is clicked, the page is re-rendered and is restored to its default state. I have made my own component which upon clicking will display further details below.

I have tried looking at React.memo and useRef, none of which worked for me. Help on this would be very much appreciated. Thanks!

Derek Nguyen
  • 11,294
  • 1
  • 40
  • 64
Keith
  • 11
  • 2

1 Answers1

0

Have tried using the 'useState' hook?

import {useState} from 'react'
function LikeButton() {
    //set default value to false
    const [liked, setLiked] = useState(false);
    const handleClick = () => {setLiked(!liked)}
    return(
        <Button color={liked? 'secondary' : 'primary'} onClick={() => handleClick()} 
    />
    );
}
export default LikeButton;

this should only re-render the button

check this out as well:

ReactJS - Does render get called any time "setState" is called?

Ahmed Nasr
  • 319
  • 5
  • 12
  • Thanks, but I cannot set the default value to false as I am updating the value of the 'liked' variable in the database. Moreover my updateSite and create function calls also update the database, which is what is causing the re-render. So I was wondering if the re-render can be stopped, and only re-render the button – Keith Aug 06 '21 at 08:57
  • I solved it! Thank you! Your answer set me down the right path, I used useState() in the end but had to tweak other things as well – Keith Aug 06 '21 at 09:28