Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

134
Vistas
Show/hide button based on state React

I have a button called download, it is a component. The functionality is written in a container.

I want the button to be hidden as default, unless the "(i === number)" condition is true in the download function.

However, it is tricky, since this condition will only be validated when I click "download". I am not sure how do I validate this logic beforehand to determine if the button needs to be displayed or not.

Can you please help? I am trying to set a state for showing button, but it doesn't work.

My code basically looks like this -

container:

state = {
  showButton: false,
};

componentDidMount() {
  this.download();
};

download = async () => {
  const data = await this.props.client
      .query({
          query: numberQuery,
          fetchPolicy: "no-cache",
      })
  // retrive data from number query ....
  const contentData = data.data.content;
 
  // retrieve and format numbers
  const numbers = this.getNumbers(contentData);
 
  // call get number and get the individual number here
  const number = await this.getNumber();
 
  numbers.forEach((i) => {
     // this is to check if numbers contain the number from getNumber(), if 
     // number matches number in numbers
     if (i === number) {
       this.setState({
        showButton: true,
       });
          // call functions, start downloading
     };
   });
  };
 
 render() {
   return (
     {this.state.showButton ? 
      <Download 
      onStartDownload={() => this.download()}
      /> : null}
    );
 };

component:

 class Download extends Component {
  state = {
    startDownload: false,
  };
 
  startDownload = () => {
    this.props.onStartDownload();
  };
 
  render() {
    return (
      <Fragment>
        <Button
          id="download"
          onClick={this.startDownload}
        >
          Download
        </Button>
      </Fragment>
     );
    };
  };
about 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

If I understand correctly, your problem is that the numbers are fetched (and, in turn, the logic for showing/hiding the button is run) only after the download button was clicked, but you want it to run as soon as possible (that is, on the component's mount).

Generally, the fetching of data in React is separated from the render/event handler logic. In your case, a solution is to fetch the data when the component mounts, save it in state (such as a numbers and number fields), then, when rendering, check if number is in the numbers array.

For example:

// Container component; child component remains the same

state = {
  number: null,
  numbers: []
};

componentDidMount() {
  this.fetchNumbers();
  this.fetchNumber();
};

async fetchNumbers() {
  const data = await this.props.client
  .query({
      query: numberQuery,
      fetchPolicy: 'no-cache',
  });
  // retrive data from number query ....
  const contentData = data.data.content;

  // retrieve and format numbers
  const numbers = this.getNumbers(contentData);

  this.setState({ numbers });
}

async fetchNumber() {
  // Assuming this is another HTTP request or something similar
  const number = await this.getNumber();

  this.setState({ number });
}

download = async () => {
  // *only* downloading logic
};
 
 render() {
    const { number, numbers } = this.state;
    const showDownload = numbers.includes(number);

    return showDownload 
        ? <Download onStartDownload={() => this.download()}/> 
        : null;
 };
}

Notes:

  • Using Array.includes() instead of an Array.forEach() loop simplifies the code (and will probably save you some bugs in the future!)
  • I separated fetchNumbers(), which fetches this.state.numbers, from fetchNumber(), which fetches this.state.number, simply because they seem like two separate pieces of state (and therefore fetching them independently is most efficient); you could improve it even further by having the two functions return the data (instead of changing the state), then using Promise.all() in componentDidMount() (I left it out for simplicity's sake).
  • Generally in web dev, a best practice when fetching core data asynchronously is to indicate that the component is not loaded until the data arrives (using a loader, for example). For practice or prototypes it might not be your top priority, but keep that in mind for production.
about 4 years ago · Santiago Trujillo Denunciar

0

you need a constructor in your class component and to update the state you need to use setState(), review the code to follow :

 class Download extends react.Component {
  constructor() {
    super();// required
    this.state = {
      startDownload: false
    };
  }

  startDownload = () => {
    this.setState((prevState) => ({
      // I use prevState, to bring the previous state value
      startDownload: !prevState.startDownload // here the value is inverted
    }));
  };

  render() {
    return (
      <> // this is equivalent to the fragment
        <button id="download" onClick={this.startDownload}>
          Download
        </button>
      </>
    );
  }
}
about 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda