TypeError: Cannot read property 'params' of undefined for updating categories

Viewed 109

So basically I'm trying to create a code that allows me to update the slug with the use of params.

Don't know why My code throws this error.

"TypeError: Cannot read property 'params' of undefined in react".

I tried replacing

useEffect(() => {
    loadCategory();
  }, []);

with

useEffect(() => {
  if(match.params.slug) loadOrders()
}, [match.params.slug])

but it still didn't work.

This is the code I wrote.

    import React, { useState, useEffect } from "react";
import {
  HistoryContainer,
  HistoryBg,
  TextContainer2,
  TextContainer3,
  Text,
  CatForm,
  FormLabel,
  FormControl,
  ButtonPrimary,
} from "./CategoryUpdateElements";
import AdminNav from "../AdminNav/index";
import { toast } from "react-toastify";
import { useSelector } from "react-redux";
import { getCategory, updateCategory } from "../../../functions/category";

const CategoryUpdate = ({ history, match }) => {
  const { user } = useSelector((state) => ({ ...state }));

  const [name, setName] = useState("");
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    loadCategory();
  }, []);

  const loadCategory = () =>
    getCategory(match.params.slug).then((c) => setName(c.data.name));

  const handleSubmit = (e) => {
    e.preventDefault();
    // console.log(name);
    setLoading(true);
    updateCategory(match.params.slug, { name }, user.token)
      .then((res) => {
        // console.log(res)
        setLoading(false);
        setName("");
        toast.success(`"${res.data.name}" is updated`);
        history.push("/admin/category");
      })
      .catch((err) => {
        console.log(err);
        setLoading(false);
        if (err.response.status === 400) toast.error(err.response.data);
      });
  };

  return (
    <>
      <HistoryContainer>
        <HistoryBg>
          <AdminNav />
          <TextContainer2>
            <TextContainer3>
              {loading ? <Text>Loading..</Text> : <Text>Update category</Text>}
              <CatForm onSubmit={handleSubmit}>
                <FormLabel>Name</FormLabel>
                <FormControl
                  type="text"
                  value={name}
                  onChange={(e) => setName(e.target.value)}
                  autoFocus
                  required
                />
                <ButtonPrimary>Save</ButtonPrimary>
              </CatForm>
            </TextContainer3>
          </TextContainer2>
        </HistoryBg>
      </HistoryContainer>
    </>
  );
};

export default CategoryUpdate;

UPDATE:

To add context to this problem. This code lets me update the name of the slug, but the TypeError doesn't let me follow through with this haha. I was actually following a tutorial regarding this and obviously, his code works. I was sure that I was following it properly as I wrote the code exactly like his but the only difference is my ui.

I also tried console logging match and after checking it out, what I saw was "undefined" which is not surprising.. It should have shown me the slug but instead it gave me "undefined".

This is his code which allows him to update his slug.

import React, { useState, useEffect } from "react";
import AdminNav from "../../../components/nav/AdminNav";
import { toast } from "react-toastify";
import { useSelector } from "react-redux";
import { getCategory, updateCategory } from "../../../functions/category";

const CategoryUpdate = ({ history, match }) => {
  const { user } = useSelector((state) => ({ ...state }));

  const [name, setName] = useState("");
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    loadCategory();
  }, []);

  const loadCategory = () =>
    getCategory(match.params.slug).then((c) => setName(c.data.name));

  const handleSubmit = (e) => {
    e.preventDefault();
    // console.log(name);
    setLoading(true);
    updateCategory(match.params.slug, { name }, user.token)
      .then((res) => {
        // console.log(res)
        setLoading(false);
        setName("");
        toast.success(`"${res.data.name}" is updated`);
        history.push("/admin/category");
      })
      .catch((err) => {
        console.log(err);
        setLoading(false);
        if (err.response.status === 400) toast.error(err.response.data);
      });
  };

  const categoryForm = () => (
    <form onSubmit={handleSubmit}>
      <div className="form-group">
        <label>Name</label>
        <input
          type="text"
          className="form-control"
          onChange={(e) => setName(e.target.value)}
          value={name}
          autoFocus
          required
        />
        <br />
        <button className="btn btn-outline-primary">Save</button>
      </div>
    </form>
  );

  return (
    <div className="container-fluid">
      <div className="row">
        <div className="col-md-2">
          <AdminNav />
        </div>
        <div className="col">
          {loading ? (
            <h4 className="text-danger">Loading..</h4>
          ) : (
            <h4>Update category</h4>
          )}
          {categoryForm()}
          <hr />
        </div>
      </div>
    </div>
  );
};

export default CategoryUpdate;

Still new to coding. Hope you guys can help me with this ^_^

1 Answers

I think your problem with match which is getting as the props. If you are having trouble with handle match props please try useRouteMatch instaed.

import { useRouteMatch } from "react-router-dom";

function YourComponent() {
  let match = useRouteMatch();

  // Do whatever you want with the match...

  return <div />;
}

I think this is more convinent to use. For more examples

Related