React useState to return a fake image with two different conditions

Viewed 341

When the two buttons are false, they return the same image, but they are next to each other, how can I make the test3 image equal for both states without having to insert another image?

 const [b1State, setB1State] = useState(false);
 const [b2State, setB2State] = useState(false);

<button onClick={() => {setB1State(!b1State)}}>Test1</button>
<button onClick={() => {setB2State(!b2State)}}>Test2</button>

{b1State ? <img src={test1} alt="" /> : <img src={test3} alt="" />}
{b2State ? <img src={test2} alt="" /> : <img src={test3} alt="" />}

The problem is when both buttons are true, and it puts one image above and one below, I believe that when one is true the other should be false.

enter image description here

3 Answers

There are 4 possible combination (0 0, 0 1, 1 0, 1 1) of 2 button states - so you need to check all of them.

And which button image to show when both are on? - you need to create a new state variable which stores the lastClicked button.

/* These constants contains image url */
const test1 = "full length apron";
const test2 = "waist apron";
const test3 = "naked";

const [b1State, setB1State] = useState(false);
const [b2State, setB2State] = useState(false);
// last clicked option will be displayed when both of them are "true" - so created a new state
const [lastClicked, setLastClicked] = useState(test1);

return(
    <>
        <button onClick={() => {setB1State(!b1State); setLastClicked(test1)}}>Test1</button>
        <button onClick={() => {setB2State(!b2State); setLastClicked(test2)}}>Test2</button>

        {/* when both the button are off - naked guy image appears */}
        { (!b2State && !b1State) && <img src={test3} alt={test3} /> }

        {/* when button 1 is on and 2 is off - full length apron image appears */}
        { (b1State && !b2State) && <img src={test1} alt={test1} /> }

        {/* when button 2 is on and 1 is off - waist apron image appears */}
        { (b2State && !b1State) && <img src={test2} alt={test2} /> }

        {/* when both the buttons are on - last button click image appears */}
        { (b1State && b2State) && <img src={lastClicked} alt={lastClicked} /> }
    </>
);

You can use a Set to ensure that an image src is included once. After creating the Set, spread it back to an array, and render using Array.map():

const { useState, useMemo } = React

const test1 = 'https://picsum.photos/id/237/100'
const test2 = 'https://picsum.photos/id/1003/100'
const test3 = 'https://picsum.photos/id/1024/100'

const Demo = () => {
  const [b1State, setB1State] = useState(false);
  const [b2State, setB2State] = useState(false);

  // create the unique array of images using a Set
  const images = useMemo(() => [...new Set([
    b1State ? test1 : test3,
    b2State ? test2 : test3,
  ])], [b1State, b2State])

  return ( 
    <div>
    <button onClick={() => {setB1State(!b1State)}}>Test1</button>
    <button onClick={() => {setB2State(!b2State)}}>Test2</button>
    
    <br />
      {images.map(src => ( // render the array
        <img key={src} src={src} alt="" />
      ))}
    </div>
  )
}

ReactDOM.render(
  <Demo />,
  root
)
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>

<div id="root"></div>

You can use this conditional render seperate for img3

{(!b1State && !b2State) && <div>show img3</div>}
{b1State && <div>show img1</div>}
{b2State && <div>show img2</div>}
Related