wilfy
wilfy

Reputation: 13

why useState change my image random onclick?

i am starting with react and I making practices for learn and i try complicate it but Im blocked because don't understand it, I have one component, that generate image and name, the name take it from a array with names, I tried with usestate change the class for the image but they generate me a new image and name with the new classname, why? I only want change this class, not generate a new image.

Thanks so much for you help.

import { useState } from 'react';
import React from 'react';
import './estilos.css';

export default function Test({ sex }) {
  var nombresHombre = ["test","test2","test3"]
  var nombresMujer = ["west","west2","west3"]
  function random(mn, mx) {
    return Math.random() * (mx - mn) + mn;
  }
  function crearHombre() {
    var nand = Math.floor(random(1, 99));
    var url = `https://randomuser.me/api/portraits/men/${nand}.jpg`;
    var nombre = nombresHombre[Math.floor(random(1, nombresHombre.length))];
    return { url, nombre };
  }
  function crearMujer() {
    var nand = Math.floor(random(1, 99));
    var url = `https://randomuser.me/api/portraits/women/${nand}.jpg`;
    var nombre = nombresMujer[Math.floor(random(1, nombresMujer.length))];
    return { url, nombre };
  }
  const primerrandom = Math.floor(Math.random() * 2 + 1);
  if (sex === 'male') {
    var persona = crearHombre();
  } else if (sex === 'female') {
    var persona = crearMujer();
  } else if (primerrandom === 1) {
    var persona = crearHombre();
  } else {
    var persona = crearMujer();
  }
  const [estado, cambioestado] = useState(true);
  const className = estado ? '' : 'disabled';
  return (
    <>
      <picture className='picture'>
        <img
          className={`imagenes ${className}`}
          onClick={() => {
            cambioestado(!estado);
          }}
          src={persona.url}
        ></img>
        <span className='span'>{persona.nombre}</span>
      </picture>
    </>
  );
}
.picture {
  display: flex;
  flex-direction: column;
  text-align: center;
  width: 100px;
}
.imagenes {
  border-radius: 70px;
  box-shadow: 0 0 15 #999;
  width: 100px;
}
.disabled {
  opacity: 0.3;
}
.span {
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

Upvotes: 0

Views: 200

Answers (1)

Nicholas Tower
Nicholas Tower

Reputation: 84902

  const primerrandom = Math.floor(Math.random() * 2 + 1);
  if (sex === 'male') {
    var persona = crearHombre();
  } else if (sex === 'female') {
    var persona = crearMujer();
  } else if (primerrandom === 1) {
    var persona = crearHombre();
  } else {
    var persona = crearMujer();
  }

This code runs every time the component renders, and since it's picking randomly, you'll get a random result on each render.

If you want to pick a random person just once, then you can use useMemo so that you don't repeat the calculation:

const persona = useMemo(() => {
  var nombresHombre = ["test","test2","test3"]
  var nombresMujer = ["west","west2","west3"]
  function random(mn, mx) {
    return Math.random() * (mx - mn) + mn;
  }
  function crearHombre() {
    var nand = Math.floor(random(1, 99));
    var url = `https://randomuser.me/api/portraits/men/${nand}.jpg`;
    var nombre = nombresHombre[Math.floor(random(1, nombresHombre.length))];
    return { url, nombre };
  }
  function crearMujer() {
    var nand = Math.floor(random(1, 99));
    var url = `https://randomuser.me/api/portraits/women/${nand}.jpg`;
    var nombre = nombresMujer[Math.floor(random(1, nombresMujer.length))];
    return { url, nombre };
  }

  const primerrandom = Math.floor(Math.random() * 2 + 1);
  if (sex === 'male') {
    return crearHombre();
  } else if (sex === 'female') {
    return crearMujer();
  } else if (primerrandom === 1) {
    return crearHombre();
  } else {
    return crearMujer();
  }
}, []); // <------------ this empty array says to never calculate again

Or you could use a state variable if you want to be able to change it later

const [persona, setPersona] = useState(() => {
  // ... same code as the previous example, ending in:
  const primerrandom = Math.floor(Math.random() * 2 + 1);
  if (sex === 'male') {
    return crearHombre();
  } else if (sex === 'female') {
    return crearMujer();
  } else if (primerrandom === 1) {
    return crearHombre();
  } else {
    return crearMujer();
  }
});

Upvotes: 1

Related Questions