Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

133
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda