`window.history.pushState()`在`URLSearchParams`上不起作用。

huangapple go评论99阅读模式
英文:

window.history.pushState() does not work on URLSearchParams

问题

以下是您要的翻译部分:

HomeScreens.js

  1. import React, { useEffect } from 'react';
  2. import { useDispatch, useSelector } from 'react-redux';
  3. import { useSearchParams } from 'react-router-dom';
  4. import Filterbar from '../components/Filterbar';
  5. // import PhotosnapIcon from '~/images/photosnap.svg';
  6. import { listJobs } from '../actions/jobActions';
  7. import './HomeScreen.scss';
  8. export default function HomeScreen() {
  9. const dispatch = useDispatch();
  10. const jobList = useSelector((state) => state.jobList);
  11. const { loading, error, jobs } = jobList;
  12. let [searchParams, setSearchParams] = useSearchParams();
  13. const params = [];
  14. searchParams.forEach((value, key) => {
  15. params.push([key, value]);
  16. });
  17. const queryParams = new URLSearchParams(params);
  18. const url = new URL(window.location.href);
  19. window.history.pushState(null, null, url);
  20. useEffect(() => {
  21. dispatch(listJobs(queryParams));
  22. console.log(jobs);
  23. }, [dispatch]);
  24. const addQuery = (key, value) => {
  25. setSearchParams((prev) => [...prev.entries(), [key, value]]);
  26. };
  27. return (
  28. <>
  29. <Filterbar />
  30. <ul>
  31. {jobs.map((job) => (
  32. <li className={job.featured ? 'post featured' : 'post'} key={job._id}>
  33. <div className="post__img-container">
  34. <img src={job.logo} alt="photosnap" />
  35. </div>
  36. <div className="post__upper-container">
  37. <div className="post__company-container">
  38. <h2 className="post__company">{job.company}</h2>
  39. {job.new && <span className="post__label new">new!</span>}
  40. {job.featured && (
  41. <span className="post__label featured">featured</span>
  42. )}
  43. </div>
  44. <h3 className="post__job-title">{job.position}</h3>
  45. <div className="post__data">
  46. <span className="post__date">{job.postedAt}</span>
  47. <div className="post__dot"></div>
  48. <span className="post__hours">{job.contract}</span>
  49. <div className="post__dot"></div>
  50. <span className="post__location">{job.location}</span>
  51. </div>
  52. </div>
  53. <div className="post__lower-container">
  54. <button
  55. className="post__category"
  56. name="role"
  57. value={job.role}
  58. onClick={(e) => addQuery('role', e.currentTarget.value)}
  59. >
  60. <span>{job.role}</span>
  61. </button>{' '}
  62. <button
  63. className="post__category"
  64. value={job.level}
  65. onClick={(e) => addQuery('level', e.currentTarget.value)}
  66. >
  67. <span>{job.level}</span>
  68. </button>
  69. {job.languages.map((language) => (
  70. <button
  71. className="post__category"
  72. name="language"
  73. value={language}
  74. onClick={(e) => addQuery('languages', e.currentTarget.value)}
  75. >
  76. <span>{language}</span>
  77. </button>
  78. ))}
  79. {job.tools.map((tool) => (
  80. <button
  81. className="post__category"
  82. name="tool"
  83. value={tool}
  84. onClick={(e) => addQuery('tools', e.currentTarget.value)}
  85. >
  86. <span>{tool}</span>
  87. </button>
  88. )}
  89. </div>
  90. </li>
  91. ))}
  92. </ul>
  93. </>
  94. );
  95. }

jobActions.js

  1. import axios from 'axios';
  2. import {
  3. JOB_LIST_REQUEST,
  4. JOB_LIST_SUCCESS,
  5. JOB_LIST_FAIL,
  6. } from '../constants/jobConstants';
  7. export const listJobs = (queryParams) => async (dispatch) => {
  8. try {
  9. dispatch({ type: JOB_LIST_REQUEST });
  10. console.log(queryParams);
  11. const { data } = await axios.get('/api/jobs', { params: queryParams });
  12. dispatch({
  13. type: JOB_LIST_SUCCESS,
  14. payload: data,
  15. });
  16. } catch (error) {
  17. dispatch({
  18. type: JOB_LIST_FAIL,
  19. payload:
  20. error.response && error.response.data.message
  21. ? error.response.data.message
  22. : error.message,
  23. });
  24. }
  25. };

backend>controller>jobs.js

  1. import ErrorResponse from '../utils/errorResponse.js';
  2. import asyncHandler from '../middleware/async.js';
  3. import Job from '../models/Job.js';
  4. // @desc Get all jobs
  5. // @routes GET /api/jobs
  6. // @access Public
  7. const getJobs = asyncHandler(async (req, res, next) => {
  8. // let query;
  9. // copy req.query
  10. const reqQuery = { ...req.query };
  11. // create query string
  12. let queryStr = JSON.stringify(reqQuery);
  13. // create operators ($gt, $gte, etc)
  14. queryStr = queryStr.replace(
  15. /\b(gt|gte|lt|lte|in)\b/g,
  16. (match) => `$${match}`
  17. );
  18. // Finding resource
  19. const jobs = await Job.find(JSON.parse(queryStr));
  20. console.log(jobs);
  21. res.json(jobs);
  22. });
英文:

Hi I am trying to pass params to backend from frontend using URLSearchParams to filter a list.
The filtering did not happen without reloading the page because URLSearchParams wasn't updated.
I wrote code as follows by searching the answers on this website but it still doesn't update.
Please tell me what is wrong.

HomeScreens.js

  1. import React, { useEffect } from &#39;react&#39;;
  2. import { useDispatch, useSelector } from &#39;react-redux&#39;;
  3. import { useSearchParams } from &#39;react-router-dom&#39;;
  4. import Filterbar from &#39;../components/Filterbar&#39;;
  5. // import PhotosnapIcon from &#39;~/images/photosnap.svg&#39;;
  6. import { listJobs } from &#39;../actions/jobActions&#39;;
  7. import &#39;./HomeScreen.scss&#39;;
  8. export default function HomeScreen() {
  9. const dispatch = useDispatch();
  10. const jobList = useSelector((state) =&gt; state.jobList);
  11. const { loading, error, jobs } = jobList;
  12. let [searchParams, setSearchParams] = useSearchParams();
  13. const params = [];
  14. searchParams.forEach((value, key) =&gt; {
  15. params.push([key, value]);
  16. });
  17. const queryParams = new URLSearchParams(params);
  18. const url = new URL(window.location.href);
  19. window.history.pushState(null, null, url);
  20. useEffect(() =&gt; {
  21. dispatch(listJobs(queryParams));
  22. console.log(jobs);
  23. }, [dispatch]);
  24. const addQuery = (key, value) =&gt; {
  25. setSearchParams((prev) =&gt; [...prev.entries(), [key, value]]);
  26. };
  27. return (
  28. &lt;&gt;
  29. &lt;Filterbar /&gt;
  30. &lt;ul&gt;
  31. {jobs.map((job) =&gt; (
  32. &lt;li className={job.featured ? &#39;post featured&#39; : &#39;post&#39;} key={job._id}&gt;
  33. &lt;div className=&quot;post__img-container&quot;&gt;
  34. &lt;img src={job.logo} alt=&quot;photosnap&quot; /&gt;
  35. &lt;/div&gt;
  36. &lt;div className=&quot;post__upper-container&quot;&gt;
  37. &lt;div className=&quot;post__company-container&quot;&gt;
  38. &lt;h2 className=&quot;post__company&quot;&gt;{job.company}&lt;/h2&gt;
  39. {job.new &amp;&amp; &lt;span className=&quot;post__label new&quot;&gt;new!&lt;/span&gt;}
  40. {job.featured &amp;&amp; (
  41. &lt;span className=&quot;post__label featured&quot;&gt;featured&lt;/span&gt;
  42. )}
  43. &lt;/div&gt;
  44. &lt;h3 className=&quot;post__job-title&quot;&gt;{job.position}&lt;/h3&gt;
  45. &lt;div className=&quot;post__data&quot;&gt;
  46. &lt;span className=&quot;post__date&quot;&gt;{job.postedAt}&lt;/span&gt;
  47. &lt;div className=&quot;post__dot&quot;&gt;&lt;/div&gt;
  48. &lt;span className=&quot;post__hours&quot;&gt;{job.contract}&lt;/span&gt;
  49. &lt;div className=&quot;post__dot&quot;&gt;&lt;/div&gt;
  50. &lt;span className=&quot;post__location&quot;&gt;{job.location}&lt;/span&gt;
  51. &lt;/div&gt;
  52. &lt;/div&gt;
  53. &lt;div className=&quot;post__lower-container&quot;&gt;
  54. &lt;button
  55. className=&quot;post__category&quot;
  56. name=&quot;role&quot;
  57. value={job.role}
  58. onClick={(e) =&gt; addQuery(&#39;role&#39;, e.currentTarget.value)}
  59. &gt;
  60. &lt;span&gt;{job.role}&lt;/span&gt;
  61. &lt;/button&gt;{&#39; &#39;}
  62. &lt;button
  63. className=&quot;post__category&quot;
  64. value={job.level}
  65. onClick={(e) =&gt; addQuery(&#39;level&#39;, e.currentTarget.value)}
  66. &gt;
  67. &lt;span&gt;{job.level}&lt;/span&gt;
  68. &lt;/button&gt;
  69. {job.languages.map((language) =&gt; (
  70. &lt;button
  71. className=&quot;post__category&quot;
  72. name=&quot;language&quot;
  73. value={language}
  74. onClick={(e) =&gt; addQuery(&#39;languages&#39;, e.currentTarget.value)}
  75. &gt;
  76. &lt;span&gt;{language}&lt;/span&gt;
  77. &lt;/button&gt;
  78. ))}
  79. {job.tools.map((tool) =&gt; (
  80. &lt;button
  81. className=&quot;post__category&quot;
  82. name=&quot;tool&quot;
  83. value={tool}
  84. onClick={(e) =&gt; addQuery(&#39;tools&#39;, e.currentTarget.value)}
  85. &gt;
  86. &lt;span&gt;{tool}&lt;/span&gt;
  87. &lt;/button&gt;
  88. ))}
  89. &lt;/div&gt;
  90. &lt;/li&gt;
  91. ))}
  92. &lt;/ul&gt;
  93. &lt;/&gt;
  94. );
  95. }

jobActions.js

  1. import axios from &#39;axios&#39;;
  2. import {
  3. JOB_LIST_REQUEST,
  4. JOB_LIST_SUCCESS,
  5. JOB_LIST_FAIL,
  6. } from &#39;../constants/jobConstants&#39;;
  7. export const listJobs = (queryParams) =&gt; async (dispatch) =&gt; {
  8. try {
  9. dispatch({ type: JOB_LIST_REQUEST });
  10. console.log(queryParams);
  11. const { data } = await axios.get(&#39;/api/jobs&#39;, { params: queryParams });
  12. dispatch({
  13. type: JOB_LIST_SUCCESS,
  14. payload: data,
  15. });
  16. } catch (error) {
  17. dispatch({
  18. type: JOB_LIST_FAIL,
  19. payload:
  20. error.response &amp;&amp; error.response.data.message
  21. ? error.response.data.message
  22. : error.message,
  23. });
  24. }
  25. };

backend>controller>jobs.js

  1. import ErrorResponse from &#39;../utils/errorResponse.js&#39;;
  2. import asyncHandler from &#39;../middleware/async.js&#39;;
  3. import Job from &#39;../models/Job.js&#39;;
  4. // @desc Get all jobs
  5. // @routes GET /api/jobs
  6. // @access Public
  7. const getJobs = asyncHandler(async (req, res, next) =&gt; {
  8. // let query;
  9. // copy req.query
  10. const reqQuery = { ...req.query };
  11. // create query string
  12. let queryStr = JSON.stringify(reqQuery);
  13. // create operators ($gt, $gte, etc)
  14. queryStr = queryStr.replace(
  15. /\b(gt|gte|lt|lte|in)\b/g,
  16. (match) =&gt; `$${match}`
  17. );
  18. // Finding resource
  19. const jobs = await Job.find(JSON.parse(queryStr));
  20. console.log(jobs);
  21. res.json(jobs);
  22. });

答案1

得分: 0

我只需要在useEffect的依赖数组中添加searchParams,以便在searchParams更改时重新渲染。当我将queryParams放入依赖数组时,会导致无限循环,所以我感到困惑,但searchParams可以正常工作。

  1. useEffect(() => {
  2. dispatch(listJobs(queryParams));
  3. }, [dispatch, searchParams]);
英文:

I just needed to add searchParams in dependency array in useEffect to re-render whenever serchParams is changed. When I put queryParams in the dep array I got indefinate loop, so I was confused, but searchParams is working.

  1. useEffect(() =&gt; {
  2. dispatch(listJobs(queryParams));
  3. }, [dispatch, searchParams]);

huangapple
  • 本文由 发表于 2023年3月1日 13:25:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/75599872.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定