0

I'm using useHistory and useLocation on two components. When passing data on history.push with a string "test" state will be "test". However, if I pass "test test" state becomes undefined. Also, useEffect runs twice which I cannot understand why. I have it pointing to search.

First Component

import React, { useState, useEffect } from "react";
import { useHistory } from "react-router-dom";

  const history = useHistory();
  const [value, setValue] = useState("");

  const onKeyPress = event => {
    if (event.key === "Enter" && event.target.value.length > 0) {
      setValue(event.target.value);
      event.preventDefault();
      history.push({
        pathname: "/home/Search",
        search: `SearchText=${value}`,
        state: { value }
      })
    }
  }

Second Component Consuming Data

import React, { useState, useEffect } from "react";
import { useLocation } from "react-router-dom";

const { search, state } = useLocation();

  useEffect(() => {
    console.log("search", search)
    console.log("state", state)
  }, [search])

Result if I pass the string "test". enter image description here

Results if I pass the string "test test". enter image description here

pt2t
  • 431
  • 1
  • 7
  • 16
  • Which version of react-router? – Phil Nov 17 '22 at 22:23
  • @Phil "react-router": "^5.2.0", – pt2t Nov 17 '22 at 22:28
  • I see the `state.value` of `"test test"` there in the logs. It seems it was passed. The `useEffect` hook likely runs twice due to `React.StrictMode` component. Can you edit the post to include a more complete and comprehensive [mcve]? Can you also provide ***exact*** reproduction steps? – Drew Reese Nov 17 '22 at 22:30
  • Why does the second state go undefined? – pt2t Nov 17 '22 at 22:31

2 Answers2

1

I think you didn't understand the asynchronous functionality, the code should be,

import React, { useState, useEffect } from "react";
import { useHistory } from "react-router-dom";

  const history = useHistory();
  const [value, setValue] = useState("");

  const onKeyPress = event => {
    if (event.key === "Enter" && event.target.value.length > 0) {
      setValue(event.target.value);
      event.preventDefault();
      history.push({
        pathname: "/home/Search",
        search: `SearchText=${event.target.value}`,
        state: { event.target.value}
      })
    }
  }

In this onKeyPress function you set, setValue(event.target.value); and after that you use that value of the useState. that is wrong. when the code execution, onkeyPress function and its all content is one block. Within that function,you can setValue it and can't use that value. possibly that value is not modified.so that you have to pass event value(event.target.value). After the onkeyPress function get executed, your setvalue will change.

And other thing is, your useEffect run twice because of the you run your React on strict mode. Let check in the index.js file that your <App/> component wrap with <React.StrictMode> </React.StrictMode>.Normally in development mode this help you to find some bugs in your code. But this twice rendering is not effect in production mode,only the developmen version.

Hope this make sense to you!

  • Thanks for answer. It definitely got me in the correct direction. My solution was to add an if statement in the useEffect. That took care of the undefined issue. – pt2t Nov 18 '22 at 01:32
0

The issue with undefined can be resolved with an if statement combined with Lakruwan Pathirage answer from above.

  useEffect(() => {
    if (state && state.length > 0) {
      const search = state;
      console.log("search", search);
    }
  }, [search])

pt2t
  • 431
  • 1
  • 7
  • 16