1

this is my first StackOverflow question:

So I have a form called datepicker, and the idea is that a user can put in a date in YYYY-MM-DD format.

Upon the submission of the entry in the field (onSubmit handler), the user is to be redirected to a /guage/:date route, that displays a guage chart component (rendered via google charts).

This guage chart is based on data pre-fetched from an API endpoint, but the {date} parameter for the API endpoint needs to be dynamic.

Meaning, when a user inputs 2022-06-09 to the date field in calendarPicker.js, there should be a redirect on submit, to the web page /guage/2022-06-09.

The problem I am having, is that the form renders, I enter a YYY-MM-DD date, the state is saved, but the handleSubmit is never triggered, and no re-direct to 'guage/:date' takes place.

Here is CalendarPicker.JS:

    import React from 'react';
import { Link, Navigate } from 'react-router-dom';

export default class CalendarPicker extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            input:''
        };

        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
      }

    handleChange(event) {
        this.setState({[event.target.name]: event.target.value});
    }

    handleSubmit(event) {
        return(
          <Navigate
          to={{
            pathname: '/guage/:input',
            state: {input: this.state.input}
          }}
          />)
      }

    render() {
        return (
            <div>  
                <form>
                    <label>date
                    <input type="text" name="input" value={this.state.input} onChange={this.handleChange} placeholder="input" required="true" />    
                    <button variant="primary" type="submit" onClick={this.handleSubmit}>
                        Submit
                    </button>
                    </label>
                </form>

            </div>

        );
    }
}

Here is DelayGuage.JS (this is where i draw the guage chart):

    //guage/2022-06-09
//const data = await Promise.resolve(resolution);
//parse URL using use params from react router
//in order to have application that scales, you need to reduce coupling between components, de-bounding components to URLs
//in order to have less coupled component and be able to render multiple components at once, using an abstraction layer, 
//known as react router, using the useparams hook, you extract the parameters without knowledge of the URL structure

import React from "react";
import { Chart } from "react-google-charts";
import axios from "axios";
import {  QueryClient, QueryClientProvider, useQuery } from 'react-query';
import { Link, useLocation, useParams } from "react-router-dom";

async function fetchPosts() {

  const {data} = await axios.get(

    "http://102.12.11.102:5000/reports/{date}/agencies"
  );
  const parsedData = data.agencies[0].kpis.map((r) => [
    "Delay Index",
    r.kpi_value * 100
  ]);

  return [["Label", "Value"], ...parsedData];
}

export const options = {
  width: 480,
  height: 480,
  redFrom: 90,
  redTo: 100,
  yellowFrom: 75,
  yellowTo: 90,
  minorTicks: 5
};

export function DelayGuage() {
  const { data, status } = useQuery("data", fetchPosts);

  return (
    status === "success" && (
      <Chart
        chartType="Gauge"
        width="100%"
        height="400px"
        data={data}
        options={options}
      />
    )
  );
}

export default DelayGuage

  • Does this answer your question? [React JS React-router-dom Navigate not working](https://stackoverflow.com/questions/70742216/react-js-react-router-dom-navigate-not-working) – code Jun 21 '22 at 19:18
  • Hello, I am implementing the solution now, it should hopefully do something, as the next challenge would be to parse the input (in its format) from the URL for the guage into a API route that takes date via axios request: async function fetchPosts() { const {data} = await axios.get( "http://102.12.11.102:5000/reports/{date}/agencies" ); const parsedData = data.agencies[0].kpis.map((r) => [ "Delay Index", r.kpi_value * 100 ]); return [["Label", "Value"], ...parsedData]; } – roastyroach Jun 21 '22 at 19:23
  • oops, it looks like that comment didnt like my code snippet – roastyroach Jun 21 '22 at 19:24

1 Answers1

1

Navigate is a React component, it needs to be rendered to have any effect. You should use the useNavigate hook if you want to issue an imperative navigation action from a callback. For this though you'll need to either convert CalendarPicker to a React function component or create a custom withRouter Higher Order Component.

Conversion:

import React from 'react';
import { Link, useNavigate } from 'react-router-dom';

const CalendarPicker = () => {
  const navigate = useNavigate();

  const [input, setInput] = React.useState('');

  const handleChange = (event) => {
    setInput(event.target.value);
  };

  const handleSubmit = (event) => {
    event.preventDefault();
    navigate(`/gauge/${input}`);
  };

  return (
    <div>  
      <form onSubmit={handleSubmit}>
        <label>
          date
          <input
            type="text"
            name="input"
            value={input}
            onChange={handleChange}
            placeholder="input"
            required
          />
        </label>
        <button variant="primary" type="submit">
          Submit
        </button>
      </form>
    </div>
  );
};

export default CalendarPicker;

withRouter HOC:

import React from 'react';
import { useNavigate, /* other hooks */ } from 'react-router-dom';

const withRouter = Component => props => {
  const navigate = useNavigate();
  // other hooks

  return (
    <Component
      {...props}
      {...{ navigate, /* other hooks props */ }}
    />
  );
};

export default withRouter;

...

import React from 'react';
import { Link } from 'react-router-dom';
import withRouter from '../path/to/withRouter';

class CalendarPicker extends React.Component {
  state = {
    input: '',
  }

  handleChange = (event) => {
    this.setState({ input: event.target.value });
  }

  handleSubmit = (event) => {
    event.preventDefault();
    this.props.navigate(`/gauge/${input}`);
  }

  render() {
    return (
      <div>  
        <form onSubmit={this.handleSubmit}>
          <label>
            date
            <input
              type="text"
              name="input"
              value={this.state.input}
              onChange={this.handleChange}
              placeholder="input"
              required
            />
          </label>
          <button variant="primary" type="submit">
            Submit
          </button>
        </form>
      </div>
    );
  }
}

export default withRouter(CalendarPicker);
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • Hello Drew! Thank you very much for the answer! The solution appears to be going somewhere, but now the route for guage is not being found, even when i have the route be "guage/:input" or even "guage/2022-06-09" in the app.js browserrouter. – roastyroach Jun 21 '22 at 19:42
  • @roastyroach What is "the gauge" and what is the error pointing to in the code? Is the issue somewhere in the `GaugePage` component? Can you clarify what you mean by "the element type as disappeared"? – Drew Reese Jun 21 '22 at 19:46
  • Hello Drew, Here is a code sandbox of my entire application below: https://codesandbox.io/s/floral-cache-mmmv3s?file=/src/Components/App.js This should help re-create the application for some context (rather than pasting code snippets). However, just for a summary, DelayGuage.JS was posted in my original post. The problem I am having is that the newly formed route "guage/{input-date}" is not fetching a generated guage. Rather, I am getting the warning "route not found", even though i had modified my route for the guage page in the app.js router-dom to be "guage/:date" – roastyroach Jun 21 '22 at 20:21
  • @roastyroach The code in the sandbox seems a little mixed up. Looks like all the root level files were placed in the `"/src/components"` directory. Can you fix and let me know when your code runs and renders the home page? – Drew Reese Jun 21 '22 at 20:39
  • Hello Drew, My apologies again, I am all very new to this. This should be a cleaned up version below: https://codesandbox.io/s/floral-cache-mmmv3s?file=/src/App.js Please let me know if this is still not working. I will just paste the snippets in a pastebin instead. However, you can refer to my original post for the "DelayGuage.js" component that is suppose to take the date in the URL from the original form input, and then put the data into the API axios call. – roastyroach Jun 21 '22 at 21:01
  • @roastyroach The `HomePanel` component file is empty. Is the home page relevant for entering a data to navigate to the gauge path, or is a hardcoded path sufficient? – Drew Reese Jun 21 '22 at 21:21
  • @roastyroach Also, just something I've noticed, `"gauge"` isn't the same string value as `"guage"`. Make sure the route path matches what you are trying to link or navigate to. – Drew Reese Jun 21 '22 at 21:24
  • The Home Panel Component file isnt suppose to be empty... let me fix that. This Home Panel Should be Correct: https://codesandbox.io/s/floral-cache-mmmv3s?file=/src/Components/Panels/HomePanel.js – roastyroach Jun 21 '22 at 21:35