Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

142
Views
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 answers
Answer question

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 Report

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 Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!