'How do I toggle between buttons in React?

I am trying to toggle between add and remove buttons in reactjs, it works fine until I reload the page, how do I make this change persist? as the button changes to "add to bin" from "remove from bin" on reload. Below is my code explaining this:

import { useMutation } from "@apollo/client";
import { UPDATE_IMAGE } from "./mutation";
import { useState } from 'react';
function NewBin(props) {
  
  
  const [uu, {err}] = useMutation(UPDATE_IMAGE);
  
  const [toggle,setToggle] = useState(false)
  
  const addBin = async () => {
    await uu({
      variables: {
        id: props.data.id,
        url: props.data.url,
        description: props.data.description,
        posterName: props.data.posterName,
        binned: true,
        userPosted: props.data.userPosted
        
      },
    });
  };

  const removeBin = async () => {
    await uu({
      variables: {
        id: props.data.id,
        url: props.data.url,
        description: props.data.description,
        posterName: props.data.posterName,
        binned: false,
        userPosted: props.data.userPosted
        
      },
    });
  };

  const comp1 = async () => {
    addBin();
    setToggle(true);
  }

  const comp2 = async () => {
    removeBin();
    setToggle(false);
  }
  
  
  return (
    <div className="Appp">
      {toggle ?  <button onClick={() => comp2()}>Remove from Bin</button>
      : <button onClick={() => comp1()}>Add to Bin</button>
      }
    </div>
  );
}

export default NewBin;

NewBin's parent:

function UnsplashPosts() {
const classes = useStyles();
  const { loading, error, data } = useQuery(unsplashImages);
  
  if(error) {
    return <h1> error</h1>;
   }
   
   if(loading) {
    return <h1> loading</h1>;
   }
 

  return (
    <div className="App">
      {data.unsplashImages.map((data) => (
        
    <Card className={classes.card} variant='outlined'>
                <CardHeader className={classes.titleHead} title={data.posterName} />
                <CardMedia
                    className={classes.media}
                    component='img'
                    image={data.url}
                    title='image'
                />

                <CardContent>
                    <Typography variant='body2' color='textSecondary' component='span'>
                        <p>{data.description}</p>

                        <NewBin data={data}/>
            <br/>
            <br/>
            <br></br>
                    </Typography>
                </CardContent>
            </Card>  
      ))}
    
    </div>
  );
}

The binned field shows true or false if it is in the bin or not.



Solution 1:[1]

You can persist the toggle state to localStorage, and initialize from localStorage.

  • Use a state initializer function to read from localStorage and provide the initial state value.
  • Use an useEffect hook to persist the updated toggle state to localStorage upon update.

Example:

function NewBin(props) {
  ...

  const [toggle, setToggle] = useState(() => {
    // Load saved state from localStorage or provide fallback
    return JSON.parse(localStorage.getItem("toggle")) ?? false;
  });

  useEffect(() => {
    // Persist state to localStorage
    localStorage.setItem("toggle", JSON.stringify(toggle));
  }, [toggle]);

  ...

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1