{window.location.href.includes("search") && !query && (
<>
<Redirect
to={{
pathname: "/search/?q=" + window.location.href.split("q=")[1],
state: {
queryString: window.location.href.split("q=")[1],
query: window.location.href.split("q=")[1],
type: type,
},
}}
></Redirect>
</>
)}
{query ? (
<Redirect
to={{
pathname: "/search/?q=" + queryString,
state: {
queryString: queryString,
query: query,
type: type,
},
}}
></Redirect>
): null}
What could I use in place in Redirect here? I need the current address (before the redirect) to be stored to the user's history, so they can still get to it using the "back" button. Or is there some extra parameter I could add to the Redirect? I tried using "from" and giving the current pathname, but that still resulted in odd behaviour (skipping a page and going to the one 2 pages back, or going "back" to the current page). Using react-router-dom but open to using something else to get what I need. The portion above is from Header.js, and below is the relevant portion from App.js (no routing/redirecting happens in SearchResult.js)
<Route path="/search/:id" exact component={SearchResult}/>
I have also tried using Route as other answers have suggested (see code below), but get an error message (Uncaught TypeError: Cannot read properties of undefined (reading 'location')
{window.location.href.includes("search") && !query && (
<Router>
<Route
to={{
pathname: "/search/?q=" + window.location.href.split("q=")[1],
state: {
queryString: window.location.href.split("q=")[1],
query: window.location.href.split("q=")[1],
type: type,
},
}}
></Route>
</Router>
)}
{query ? (
<Router>
<Route
to={{
pathname: "/search/?q=" + queryString,
state: {
queryString: queryString,
query: query,
type: type,
},
}}
></Route>
</Router>
): null}
Edit: As requested, please see below more context for this code. I have omitted some functions which only affect styling (change text content of search bar instructions, colour of certain objects, etc, and functions which handle settings when the page loads:
Relevant sections of Header.js (when I uncomment the setQuery(false) lines, the search executes but displays the result that is already on the page, not the one the user typed into the search bar. For example, if I am already on "/search/?q=sleep" and type "dance" into the search bar and hit enter, I will be taken to the same page I am on (the search results for "sleep". The behaviour when hitting the "back" button is also similar):
//contains search bar where user inputs their query
//this is represented by queryString
//handleSearchKey is called every time the user types
function Header(props) {
const [queryString, setQueryString] = useState("");
const [query, setQuery] = useState(false);
const [type, setDispType] = useState("Latn");
const handleSearchKey = (e) => {
if (e.target.value === "" && e.key !== "Enter") {
e.target.labels[0].innerText = "Search in Cree or English";
//setQuery(false);
}
if (e.key === "Enter" && queryString && queryString !== "") {
setQuery(true);
setShowNoQueryAlert(false);
window.dispatchEvent(new Event("executeSearch"));
}
else if (e.key === "Enter") {
setShowNoQueryAlert(true);
//setQuery(false);
}
else {
setQueryString(e.target.value);
//setQuery(false);
}
};
//start search when magnifynig glass icon is clicked
const handleMagGlassClick = (e) => {
if (queryString) {
setQuery(true);
window.dispatchEvent(new Event("executeSearch"));
} else {
setShowNoQueryAlert(true);
}
};
window.onpopstate = function(e) { //prevents blank page when using "back" button
window.location.reload();
}
console.log("**********************");
console.log("HISTORY:", document.referrer);
console.log("query:", query);
console.log("queryString:", queryString);
console.log("***************")
return (
<div className="top-bar app__header">
{query ? (
<Redirect
push to={{
pathname: "/search/?q=" + queryString,
state: {
queryString: queryString,
query: false,
type: type,
},
}}
></Redirect>
) : console.log("no query")}
<Snackbar open={showNoQueryAlert} autoHideDuration={6000} onClose={handleClose} anchorOrigin={{vertical: "bottom", horizontal: "center"}}>
<Alert onClose={handleClose} severity="error">
Please enter a word or a phrase to search
</Alert>
</Snackbar>
<nav className="search top-bar__search">
<TextField
id="search"
className="search-bar"
variant="outlined"
width={"60%"}
fullWidth
label="Search in Cree or English"
autoComplete="off" //prevents history from popping up
onFocus={setEnterMessage}
onBlur={setDefaultMessage}
//styling for label text
InputLabelProps={
{
style:{
fontStyle: "italic",
fontFamily: "", //other acceptable fonts? - Tahoma, Segoe UI, Microsoft PhagsPa, Microsoft YaHei, Nirmala UI
fontSize: "160%",
marginTop: "-7px",
color: "gray",
}
}
}
size="small"
InputProps={{
endAdornment: (
<InputAdornment position="end">
<Button onClick={handleMagGlassClick} onMouseDown={(e)=> {e.preventDefault()} } className="mag-glass-btn" >
<FontAwesomeIcon icon={faMagnifyingGlass} size="xl" color="gray"> </FontAwesomeIcon>
</Button>
</InputAdornment>
),
style: {backgroundColor: "white", fontStyle: "normal", borderRadius: "15px"}, //look of searchbar
}}
onKeyUp={handleSearchKey}
></TextField>
</nav>
<nav className="top-bar__nav">
<details className="toggle-box toggle-box--with-menu close-on-click-away">
<summary
id="settings-menu__button"
className="toggle-box__toggle"
data-cy="settings-menu"
aria-haspopup="menu"
tabIndex="0"
>
Settings
</summary>
<div
className="menu toggle-box__menu"
aria-labelledby="settings-menu__button"
>
<div className="menu__category">
<h3 className="menu__header">
Show {sourceLanguageName} words in…
</h3>
<ul className="menu__choices" data-cy="orthography-choices">
{/* list of setting menu */}
{Object.keys(settingMenu).map((id, index) => (
<li className="menu-choice" key={index}>
<button
style={{backgroundColor: handleHighlightedSettings(id)}}
data-orth-switch
value={id}
className="unbutton fill-width"
onClick={() => handleSettingChange(id)}
>
<span className="menu-choice__label">
{settingMenu[id]}
{id == "Cans" && <hr style={{marginTop: "1.3em", marginBottom: "-0.5em"}} className="menu__separator"></hr>}
</span>
</button>
</li>
))}
</ul>
</div>
<hr style={{marginTop: "0.5em", marginBottom: "1em", marginLeft: "1.3em", marginRight: "1.3em"}} className="menu__separator"></hr>
<div className="menu__category">
<a
href="/settings"
className="menu-choice"
data-cy="settings-link"
>
<span className="menu-choice__label fill-width" style={{marginTop: "-0.5em", marginBottom: "0.5em"}}>
View all settings
</span>
</a>
</div>
</div>
</details>
</nav>
</div>
);
}
export default Header;
Relevant sections of App.js (this js file contains all routes):
<Route path="/search/:id" exact component={SearchResult}/>
Relevant sections of SearchResult.js (after fetching it just displays the results):
//fetches results when user hits "enter" button or clicks magnifying glass in Header.js
function SearchResult(props){
const apiUrl = process.env.REACT_APP_BACKEND
const query = props.location.state.queryString;
async function getAllData() {
if (query === "") {
return [];
}
return fetch(`${apiUrl}/api/search/?name=${query}`).then((res) =>
res.json()
);
}
async function getMyResults() {
let namedData = await getAllData();
try {
// namedData = JSON.parse(namedData);
return namedData["search_results"];
} catch (err) {
return "empty";
}
}
const { isFetching, error, data, refetch } = useQuery(
"getMyResults",
() => getMyResults(),
{
refetchOnWindowFocus: false,
}
);
window.addEventListener("executeSearch", () => refetch());