import SearchIcon from '@material-ui/icons/Search';
import MicIcon from '@material-ui/icons/Mic';
import {Button} from '@material-ui/core';
import styled from 'styled-components';
//import {Search} from '@material-ui/icons';
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useStateValue } from '../SearchProvider.js';
import { SET_SEARCH_TERM } from '../types.js';
import React from 'react';
const SearchInput = styled.div`
display: flex;
align-items: center;
border: 1px solid lightgray;
height 30px;
padding: 10px 15px;
width: 500px;
margin: 0px auto;
border-radius: 999px;
input {
flex: 1;
padding: 8px 13px;
font-size: medium;
border: 0;
outline: 0;
}
.searchicon {
color: gray;
}
`;
const SearchButton = styled.div`
margin-top: 20px;
display: flex;
justify-content: center;
button {
margin: 5px;
background: #f8f8f8 !important;
border: 1px solid white;
text-transform: inherit;
&:hover {
margin: 5px;
background: #f8f8f8 !important;
color: #000;
border: 1px solid #c6c6c6
}
}
`;
const Search = ({ hide }) => {
const [input, setInput] = useState("");
const navigate = useNavigate();
const[{}, dispatch] = useStateValue();
const search = e => {
e.preventDefault();
dispatch({
type: SET_SEARCH_TERM,
term: input
})
console.log(input);
navigate.push("/search");
};
return (
<form onSubmit={search}>
<SearchInput>
<SearchIcon className="searchicon" />
<input value={input} onChange={e => setInput(e.target.value)} />
<MicIcon />
</SearchInput>
{!hide && (
<SearchButton>
<Button type="submit" variant="outlined">Google Search</Button>
<Button variant="outlined">I am feeling lucky</Button>
</SearchButton>
)}
</form>
)
};
export default Search
I am trying to make a google clone but I am getting errors in my console saying "Uncaught Error: useNavigate() may be used only in the context of a component" and i'm not sure what else to do. Says the error is coming in the "const navigate = useNavigate();" line. I have tried using "Navigate" and "useHistory" as well but those are working either.
CodePudding user response:
The useStateValue hook is a custom hook that is used to manage global state in your application. It returns an array with two elements: the current global state, and a dispatch function that can be used to update the global state. In the original code, the array was destructured like this:
const [{}, dispatch] = useStateValue();
The problem with this code is that the first element of the array is being destructured as an empty object {}, and it is not being used. This can cause confusion and make the code harder to understand.
To fix this, I modified the destructuring assignment to extract only the dispatch function from the array, like this:
const [, dispatch] = useStateValue();
This will ensure that the dispatch function is available for use, without extracting and discarding the current global state.
As for the second fix, the useNavigate hook is a custom hook that is provided by the react-router-dom library. It returns a function that can be used to navigate to a different location in your application.
In the original code, the push method was being called on the navigate function, like this:
navigate.push('/search');
However, the navigate function does not have a push method. To fix this, I modified the code to call the navigate function directly, like this:
navigate('/search')
This will correctly navigate to the /search location in your application.
I hope this helps!
CodePudding user response:
A react-router
or react-router-dom
router component provides the routing context that all routes, links, hooks, etc use. The Search
component needs to be rendered within router so the useNavigate
hook has a routing context available to it.
Example:
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import Search from '../components/Search';
...
const App = () => {
...
return (
<BrowserRouter> // <-- Provides routing context
<div>
...
<Search /> // <-- rendered within Router component
</div>
<Routes>
.... app routes ...
</Routes>
...
</BrowserRouter>
);
};
Also, just FYI, navigate
is a function, not an object like history
that was used in previous versions. Use navigate("/search");
instead of navigate.push("/search");
to issue an imperative navigation action.