Is there a way to convert time measurements like minutes, hours, or days into seconds in React and then pass that information to an

Currently, I am working on an application that allows users to select a frequency unit (like seconds, minutes, hours, or days) and input the corresponding value. The challenge arises when I need to convert this value into seconds before sending it to the server. While sending the value in seconds works perfectly fine, I encounter issues while converting it back to minutes, hours, or days. For instance, if I try to send a value of 10 minutes, the server ends up receiving "10" instead of the correct value of "600" (10 minutes * 60 seconds). Can anyone provide insights or suggestions on what might be causing this discrepancy in my code?

import React, { Component } from 'react';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { addSensor } from '../actions/sensors';

class AddSensorPage extends Component {
  state = {  
    name: '',
    category: '',
    frequencyUnit: '',
    frequency: '',
    minValue: '',
    maxValue: ''
  }

  static propTypes = {
    addSensor: PropTypes.func.isRequired
  }

  handleChange = e => {
    this.setState({
      [e.target.name]: e.target.value,
    })
  }

  handleCategorySelect = e => {
    this.setState({ category: e.target.value })
  }

  handleFrequencyUnitSelect = e => {
    this.setState({ frequencyUnit: e.target.value })
  }

  handleSubmit = e => {
    e.preventDefault();

    const { name, category, frequency, frequencyUnit } = this.state;

    // Validation
    if (frequencyUnit === 'seconds') {
      this.setState({
        minValue: '30',
        maxValue: '21474836',
      })
    }

    if (frequencyUnit === 'minutes') {
      this.setState({
        minValue: '1',
        maxValue: '357913',
        frequency: this.state.frequency * 60
      })
    }

    if (this.state.frequencyUnit === 'hours') {
      this.setState({
        minValue: '1',
        maxValue: '5965',
        frequency: frequency * 3600
      })
    }

    if (this.state.frequencyUnit === 'days') {
      this.setState({
        minValue: '1',
        maxValue: '248',
        frequency: frequency * 86400
      })
    }

    const sensor = { name, category, frequency };

    this.props.addSensor(sensor);

    this.setState({
      name: '',
      category: '',
      frequencyUnit: '',
      frequency: ''
    })
  }

  render() { 
    return (  
      <div className="col-md-6 m-auto">
        <div className="card card-body mt-5">
          <h2 className="text-center">Add sensor</h2>
          <form onSubmit={this.handleSubmit}>
            <div className="form-group">
              <label>Name</label>
              <input
                type="text"
                className="form-control"
                name="name"
                onChange={this.handleChange}
                value={this.state.name}
              />
            </div>
            <div className="form-group">
              <label>Category</label>
              <select className="form-control" onChange={this.handleCategorySelect} value={this.state.category}>
                <option></option>
                <option value="temperature">Temperature sensor</option>
                <option value="humidity">Humidity sensor</option>
              </select>
            </div>
            <div className="form-group">
              <label>Frequency</label>
              <select className="form-control" onChange={this.handleFrequencyUnitSelect} value={this.state.frequencyUnit}>
                <option></option>
                <option value="seconds">Seconds</option>
                <option value="minutes">Minutes</option>
                <option value="hours">Hours</option>
                <option value="days">Days</option>
              </select>
            </div>
            <div className="form-group">
              <input
                type="number"
                className="form-control"
                name="frequency"
                onChange={this.handleChange}
                value={this.state.frequency}
                placeholder="Value..."
                min={this.state.minValue}
                max={this.state.maxValue}
              />
            </div>
            <div className="form-group">
              <button className="btn btn-primary">Dodaj</button>
            </div>
          </form>
        </div>
      </div>
    );
  }
}

export default connect(null, { addSensor })(AddSensorPage); 

Answer №1

The problem arises due to the asynchronous nature of setState

import React, { Component } from "react";
import { connect } from 'react-redux';
import PropTypes from "prop-types";
import { addSensor } from '../actions/sensors';

class AddSensorPage extends Component {
  state = {
    name: "",
    category: "",
    frequencyUnit: "",
    frequency: "",
    minValue: "",
    maxValue: ""
  };

  static propTypes = {
    addSensor: PropTypes.func.isRequired
  };

  handleChange = e => {
    this.setState({
      [e.target.name]: e.target.value
    });
  };

  handleCategorySelect = e => {
    this.setState({ category: e.target.value });
  };

  handleFrequencyUnitSelect = e => {
    this.setState({ frequencyUnit: e.target.value });
  };

  callBack = () => {
    let sensor = {};
    sensor = {
      name: this.state.name,
      category: this.state.category,
      frequency: this.state.frequency
    };
    console.log(sensor);
    this.props.addSensor(sensor);
    this.setState({
      name: "",
      category: "",
      frequencyUnit: "",
      frequency: ""
    });
  };

  handleSubmit = e => {
    e.preventDefault();

    const { name, category, frequency, frequencyUnit } = this.state;

    // Validation

    if (frequencyUnit === "seconds") {
      this.setState(
        {
          minValue: "30",
          maxValue: "21474836"
        },
        () => {
          this.callBack();
        }
      );
    }

    if (frequencyUnit === "minutes") {
      this.setState(
        {
          minValue: "1",
          maxValue: "357913",
          frequency: frequency * 60
        },
        () => {
          this.callBack();
        }
      );
    }

    if (this.state.frequencyUnit === "hours") {
      this.setState(
        {
          minValue: "1",
          maxValue: "5965",
          frequency: frequency * 3600
        },
        () => {
          this.callBack();
        }
      );
    }

    if (this.state.frequencyUnit === "days") {
      this.setState(
        {
          minValue: "1",
          maxValue: "248",
          frequency: frequency * 86400
        },
        () => {
          this.callBack();
        }
      );
    }
    // console.log("This is the sensor", sensor);

  };

  render() {
    return (
      <div className="col-md-6 m-auto">
        <div className="card card-body mt-5">
          <h2 className="text-center">Add sensor</h2>
          <form onSubmit={this.handleSubmit}>
            <div className="form-group">
              <label>Name</label>
              <input
                type="text"
                className="form-control"
                name="name"
                onChange={this.handleChange}
                value={this.state.name}
              />
            </div>
            <div className="form-group">
              <label>Category</label>
              <select
                className="form-control"
                onChange={this.handleCategorySelect}
                value={this.state.category}
              >
                <option />
                <option value="temperature">Temperature sensor</option>
                <option value="humidity">Humidity sensor</option>
              </select>
            </div>
            <div className="form-group">
              <label>Frequency</label>
              <select
                className="form-control"
                onChange={this.handleFrequencyUnitSelect}
                value={this.state.frequencyUnit}
              >
                <option />
                <option value="seconds">Seconds</option>
                <option value="minutes">Minutes</option>
                <option value="hours">Hours</option>
                <option value="days">Days</option>
              </select>
            </div>
            <div className="form-group">
              <input
                type="number"
                className="form-control"
                name="frequency"
                onChange={this.handleChange}
                value={this.state.frequency}
                placeholder="Value..."
                min={this.state.minValue}
                max={this.state.maxValue}
              />
            </div>
            <div className="form-group">
              <button className="btn btn-primary">Dodaj</button>
            </div>
          </form>
        </div>
      </div>
    );
  }
}

//export default AddSensorPage;
export default connect(null, { addSensor })(AddSensorPage);

Also check out this functional demo on CodeSandbox: example

Answer №2

You rely on the same state for fetching values in your code. Why not simplify it?

if (frequencyUnit === "minutes") {
  this.setState({
    minValue: "1",
    maxValue: "357913",
    frequency
  });
}

and

const sensor = {
  name,
  category,
  frequency: frequency * multiplier[frequencyUnit]
};

where multiplier is:

const multiplier = {
  seconds: 1,
  minutes: 60,
  hours: 3600,
  days: 86400
};

This method is still not optimal. It's not advisable to directly set the state in the submit section like that. Once again, this approach is simplistic. Consider a more thoughtful way of setting the app state.

Here's a more efficient approach:

const units = {
  seconds: {
    name: "seconds",
    multiplier: 1,
    minValue: "30",
    maxValue: "21474836"
  },
  minutes: {
    name: "minutes",
    multiplier: 60,
    minValue: "1",
    maxValue: "357913"
  },
  hours: { name: "hours", multiplier: 3600, minValue: "1", maxValue: "5965" },
  days: { name: "days", multiplier: 86400, minValue: "1", maxValue: "248" }
};

class App extends React.Component {
  state = {
    name: "",
    category: "",
    frequencyUnit: {},
    frequency: "",
    minValue: "",
    maxValue: ""
  };

  handleChange = e => {
    this.setState({
      [e.target.name]: e.target.value
    });
  };

  handleCategorySelect = e => {
    this.setState({ category: e.target.value });
  };

  handleFrequencyUnitSelect = e => {
    this.setState({ frequencyUnit: units[e.target.value] });
  };

  handleSubmit = e => {
    e.preventDefault();

    const { name, category, frequency, frequencyUnit } = this.state;

    const sensor = {
      name,
      category,
      frequency: frequency * frequencyUnit.multiplier
    };

    console.log(sensor);
    //this.props.addSensor(sensor);

    this.setState({
      name: "",
      category: "",
      frequencyUnit: {},
      frequency: ""
    });
  };

  render() {
    return (
      <div className="col-md-6 m-auto">
        <div className="card card-body mt-5">
          <h2 className="text-center">Add sensor</h2>
          <form onSubmit={this.handleSubmit}>
            <div className="form-group">
              <label>Name</label>
              <input
                type="text"
                className="form-control"
                name="name"
                onChange={this.handleChange}
                value={this.state.name}
              />
            </div>
            <div className="form-group">
              <label>Category</label>
              <select
                className="form-control"
                onChange={this.handleCategorySelect}
                value={this.state.category}
              >
                <option />
                <option value="temperature">Temperature sensor</option>
                <option value="humidity">Humidity sensor</option>
              </select>
            </div>
            <div className="form-group">
              <label>Frequency</label>
              <select
                className="form-control"
                onChange={this.handleFrequencyUnitSelect}
                value={this.state.frequencyUnit.name || ""}
              >
                <option />
                <option value="seconds">Seconds</option>
                <option value="minutes">Minutes</option>
                <option value="hours">Hours</option>
                <option value="days">Days</option>
              </select>
            </div>
            <div className="form-group">
              <input
                type="number"
                className="form-control"
                name="frequency"
                onChange={this.handleChange}
                value={this.state.frequency}
                placeholder="Value..."
                min={this.state.frequencyUnit.minValue}
                max={this.state.frequencyUnit.maxValue}
              />
            </div>
            <div className="form-group">
              <button className="btn btn-primary">Dodaj</button>
            </div>
          </form>
        </div>
      </div>
    );
  }
}

ReactDOM.render(
    <App />,
  document.getElementById("root")
);
<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>
<div id="root" />

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Repeating X and Y Axis Labels on Highcharts

Highchart is new to me. I recently created a basic chart showing the count of males and females over the past five years. I have included a screenshot for reference. I am wondering if it's possible to remove duplicate labels from both axes? Below is ...

Utilizing Ajax, Jquery, and Struts2 for File Uploading

Can someone please provide guidance on uploading files using a combination of Ajax, jQuery, and Struts2? I have searched through numerous tutorials online but haven't found a suitable solution yet. The goal is to trigger a JavaScript function when a b ...

What is the best way to retrieve the selected value from a React select component?

Here is my code, can someone please assist me? I seem to be encountering an issue. const options = [ { value: 'chocolate', label: 'Chocolate' }, { value: 'strawberry', label: 'Strawberry' }, { value: &apo ...

Clicking on a custom Material UI autocomplete popper will cause it to close automatically

While working on the Material UI autocomplete paper, I attempted to include a button by overriding the PaperComponent prop. However, when I added a button at the bottom of the paper and clicked on it, the autocomplete search results would automatically clo ...

Using Axios in Vuejs to prompt a file download dialog

I am currently working on figuring out how to trigger a file download dialog box after receiving an Ajax request from the Flask server using Axios. Here is my current client-side code snippet: <script> export default { ... exportCSV: function() { ...

Error in NodeJS testing: Attempting to read property 'apply' of an undefined value

I am delving into the world of Jest unit testing and exploring NodeJS for the first time. Currently, I am attempting to test my API using the code snippet below: const request = require('supertest'); const quick_registration = require('../. ...

Refresh the dataTable once all external data has been successfully fetched

I am struggling to find the correct method for reloading a datatable. Here is my current process: Retrieve data through ajax for specific columns Generate a table with the fetched data Initialize the datatable for the table Make a new ajax request using ...

Transmitting JSON data object

Sending a JSON Object to JSP Page After following the provided link, I discovered that one of the answers suggests creating a JSON object using the following constructor: JSONObject jsonObj=new JSONObject(String_to_Be_Parsed); Upon downloading the JSON ...

Combining react-draggable and material-ui animations through react-transition group: a comprehensive guide

Trying to incorporate react-draggable with material-UI animations. One approach is as follows: <Draggable> <Grow in={checked}> <Card className={clsx(classes.abs, classes.paper)}> <svg classN ...

Which method is better for HTML5/JavaScript GeoLocation: Passing data to a callback function or suspending an async call using promises?

Trying to figure out how to utilize HTML5/Javascript Geolocations effectively for passing location data to an ajax call and storing it in a database. The main challenges I'm facing are the asynchronous nature of the Geolocation call and issues with va ...

Transforming the date from JavaScript to the Swift JSON timeIntervalSinceReferenceDate structure

If I have a JavaScript date, what is the best way to convert it to match the format used in Swift JSON encoding? For example, how can I obtain a value of 620102769.132999 for a date like 2020-08-26 02:46:09? ...

Stopping all animations with JQuery animate()

I have a question about stopping multiple animations. Here's some pseudocode to illustrate my situation: CSS #div1 { position: absolute; background-image: url("gfx/cat.jpg"); width: 60px; height: 70px; background-size: 50%; b ...

Guide on Implementing Link href in Next.js v12

When I set the href as a string, the link functions properly. However, when I use an object for the href, the link fails to work. Despite seeing the correct querystring when hovering over the link, it always takes me back to the first page. // ProdCard t ...

Error message: The getList dataProvider function is unknown in react admin

I'm currently retrieving data from a mongoDB database to display on a react admin panel. The framework I'm using is react-admin. Instead of using id, I am fetching the data with _id. [ { "_id": "61f665cc0389af42ef103932 ...

IntelliJ does not support the use of newlines within Vue.js component templates

While working with Vue.js in IntelliJ IDEA, I encountered a small problem related to defining component templates. The issue is that IntelliJ seems to struggle when the template spans more than one line and attempts to concatenate them together. For examp ...

What is the best way to transfer the http server variable between different layers in node.js without requiring it in a separate file?

I've developed a nodeJS application that involves creating a server in the file server.js. The code looks like this: http.createServer(app).listen(app.get('port'), function (err) { if (err) { console.error(err); } else { ...

Develop a versatile JavaScript or jQuery script that automatically sets the focus on the first input field within a div or tag when the user clicks on it

I am currently working on creating a data entry form using a table layout. The form has two columns - the first column for input titles and the second column mostly for input tags. I styled the inputs in the second column to appear transparent with no bord ...

Steps to retrieve the latest value of a specific cell within the Material UI Data Grid

After updating the cell within the data grid, I encountered an issue where I could retrieve the ID and field using the prop selectedCellParams, but retrieving the modified value was proving to be challenging. In order to successfully execute the PUT reque ...

Adjust SVG size as per parent container in AngularJS custom directive

I have a unique situation where I am integrating an angular directive into a dynamically-sized element. The directive itself is made up of an SVG which adjusts based on the size of the container. I am working on making sure the SVG automatically resizes an ...

Themes in Next.js with a splash of color

Is there a way to implement theming with color picking for elements? Check out the example here. I've explored using CSS variables and changing the document classname, but I'm uncertain if this is the best approach. @tailwind base; @tailwind com ...