0

I want a table of data to refresh on button click after the POST request has been submitted.

I have a react button:

<Button onClick={this.click} className="domain-button" type='primary'>Add</Button>

And the corresponding click function, and refreshPage function:

async click() {
  const { domainInputValue } = this.state;
  console.log( domainInputValue );

  const response = await
  fetch('/new-cert', {
      headers: {
          'Content-Type': 'application/json'
      },

      method: 'POST',
      body: JSON.stringify({domainInput: domainInputValue})
  });

  const body = await response.text()
  console.log(body)

  if (response.status !== 200) throw Error(body.message);
  return body;
}

refreshPage() {
  window.location.reload();
}

And in my back-end Nodejs to handle the POST request I have:

app.post('/new-cert', function (req, res) {
    fs.appendFile('certs-list', '\n' + req.body.domainInput, function (err) {
        if (err) throw err;
    });
    res.send('POST request: ');

    console.log("INSERTING")
    exec('sh cert-check-script-insert.sh');

    console.log(req.body);
    console.log('post is working!')
});

I'm not sure where to call refreshPage(), I've tried calling it right after click() but this seems to be too early and the refresh does not change the data displayed in the table.

tnoel999888
  • 584
  • 3
  • 12
  • 29
  • You could have a `posted` variable in `state`, which changes after the POST. This will cause the component to re-render, which seems to be what you want. – Colin Ricardo Apr 17 '18 at 15:57
  • @Colin thanks for the suggestion, could you possibly write an answer please, just not sure where to put things – tnoel999888 Apr 17 '18 at 16:06

3 Answers3

0

Delay the server response until the server is ready for the reload - in your case, looks like you should do res.send and maybe also exec inside the callback to fs.appendFile. Then your fetch will not resolve until the server is definitely ready, and you do your reload then.

Refreshing the whole page to get new data is not very React, but that's none of my business.

Ben West
  • 4,398
  • 1
  • 16
  • 16
  • Should I just be re-rendering the component? And if so could you suggest how to, sorry I'm new to this – tnoel999888 Apr 17 '18 at 16:04
  • Yeah, something like that. Where does the new data come from when you reload? – Ben West Apr 17 '18 at 16:05
  • Maybe you could send the new data back as the response from the POST request and solve both problems at once. – Ben West Apr 17 '18 at 16:07
  • It's coming from a back-end API with path `/list-certs` that comes from a local file called `certs.json`. I've tried to add a `fs.readFile` call to `certs.json` after the `fs.appendFile` call to `certs-list` if that's what you mean? – tnoel999888 Apr 18 '18 at 09:50
  • So your component is doing another `fetch` to get the data? You should be able to make it do that again instead of refreshing everything. – Ben West Apr 18 '18 at 10:43
0

Put the refreshPage() call after await response.text():

async click() {
  const { domainInputValue } = this.state;
  console.log( domainInputValue );

  const response = await
  fetch('/new-cert', {
      headers: {
          'Content-Type': 'application/json'
      },

      method: 'POST',
      body: JSON.stringify({domainInput: domainInputValue})
  });

  const body = await response.text()

  refreshPage();

  console.log(body)

  if (response.status !== 200) throw Error(body.message);
  return body;
}

I agree with @ben-west, though -- I'd recommend using state in React to handle this. Essentially, you'll want to setState with whatever data you care about from the response, and then use that data from this.state wherever you need it in your component.

camden
  • 1,908
  • 19
  • 18
  • Thanks for the answer but it seems to be a premature reload as it doesn't display the new data and I have to reload again for it to appear. Could you possibly write an answer using States please? I'm new to React and Nodejs and still trying to get my head around it – tnoel999888 Apr 18 '18 at 09:08
0

I ended up adding a function componentDidUpdate() which mimics my componentDidMount() behaviour:

componentDidMount() {
    this.callApi()
        .then(res => {
            this.setState({
                json: res.map(x => x),
            })
        })
        .catch(err => console.log(err));
}


componentDidUpdate() {
    this.callApi()
        .then(res => {
            this.setState({
                json: res.map(x => x),
            })
        })
        .catch(err => console.log(err));
}
tnoel999888
  • 584
  • 3
  • 12
  • 29
  • 1
    If you're duplicating code like this, I'd recommend pulling this out into a function and calling it from `componentDidUpdate` and `componentDidMount`. – camden May 07 '18 at 16:24