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

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

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

问题

以下是您要的翻译部分:

HomeScreens.js

import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { useSearchParams } from 'react-router-dom';
import Filterbar from '../components/Filterbar';
// import PhotosnapIcon from '~/images/photosnap.svg';
import { listJobs } from '../actions/jobActions';

import './HomeScreen.scss';

export default function HomeScreen() {
  const dispatch = useDispatch();

  const jobList = useSelector((state) => state.jobList);
  const { loading, error, jobs } = jobList;

  let [searchParams, setSearchParams] = useSearchParams();

  const params = [];

  searchParams.forEach((value, key) => {
    params.push([key, value]);
  });

  const queryParams = new URLSearchParams(params);

  const url = new URL(window.location.href);
  window.history.pushState(null, null, url);

  useEffect(() => {
    dispatch(listJobs(queryParams));
    console.log(jobs);
  }, [dispatch]);

  const addQuery = (key, value) => {
    setSearchParams((prev) => [...prev.entries(), [key, value]]);
  };

  return (
    <>
      <Filterbar />
      <ul>
        {jobs.map((job) => (
          <li className={job.featured ? 'post featured' : 'post'} key={job._id}>
            <div className="post__img-container">
              <img src={job.logo} alt="photosnap" />
            </div>
            <div className="post__upper-container">
              <div className="post__company-container">
                <h2 className="post__company">{job.company}</h2>
                {job.new && <span className="post__label new">new!</span>}
                {job.featured && (
                  <span className="post__label featured">featured</span>
                )}
              </div>
              <h3 className="post__job-title">{job.position}</h3>
              <div className="post__data">
                <span className="post__date">{job.postedAt}</span>
                <div className="post__dot"></div>
                <span className="post__hours">{job.contract}</span>
                <div className="post__dot"></div>
                <span className="post__location">{job.location}</span>
              </div>
            </div>
            <div className="post__lower-container">
              <button
                className="post__category"
                name="role"
                value={job.role}
                onClick={(e) => addQuery('role', e.currentTarget.value)}
              >
                <span>{job.role}</span>
              </button>{' '}
              <button
                className="post__category"
                value={job.level}
                onClick={(e) => addQuery('level', e.currentTarget.value)}
              >
                <span>{job.level}</span>
              </button>
              {job.languages.map((language) => (
                <button
                  className="post__category"
                  name="language"
                  value={language}
                  onClick={(e) => addQuery('languages', e.currentTarget.value)}
                >
                  <span>{language}</span>
                </button>
              ))}
              {job.tools.map((tool) => (
                <button
                  className="post__category"
                  name="tool"
                  value={tool}
                  onClick={(e) => addQuery('tools', e.currentTarget.value)}
                >
                  <span>{tool}</span>
                </button>
              )}
            </div>
          </li>
        ))}
      </ul>
    </>
  );
}

jobActions.js

import axios from 'axios';

import {
  JOB_LIST_REQUEST,
  JOB_LIST_SUCCESS,
  JOB_LIST_FAIL,
} from '../constants/jobConstants';

export const listJobs = (queryParams) => async (dispatch) => {
  try {
    dispatch({ type: JOB_LIST_REQUEST });

    console.log(queryParams);

    const { data } = await axios.get('/api/jobs', { params: queryParams });

    dispatch({
      type: JOB_LIST_SUCCESS,
      payload: data,
    });
  } catch (error) {
    dispatch({
      type: JOB_LIST_FAIL,
      payload:
        error.response && error.response.data.message
          ? error.response.data.message
          : error.message,
    });
  }
};

backend>controller>jobs.js

import ErrorResponse from '../utils/errorResponse.js';
import asyncHandler from '../middleware/async.js';
import Job from '../models/Job.js';

// @desc Get all jobs
// @routes GET /api/jobs
// @access Public
const getJobs = asyncHandler(async (req, res, next) => {
  // let query;

  // copy req.query
  const reqQuery = { ...req.query };

  // create query string
  let queryStr = JSON.stringify(reqQuery);

  // create operators ($gt, $gte, etc)
  queryStr = queryStr.replace(
    /\b(gt|gte|lt|lte|in)\b/g,
    (match) => `$${match}`
  );

  // Finding resource
  const jobs = await Job.find(JSON.parse(queryStr));

  console.log(jobs);

  res.json(jobs);
});
英文:

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

import React, { useEffect } from &#39;react&#39;;
import { useDispatch, useSelector } from &#39;react-redux&#39;;
import { useSearchParams } from &#39;react-router-dom&#39;;
import Filterbar from &#39;../components/Filterbar&#39;;
// import PhotosnapIcon from &#39;~/images/photosnap.svg&#39;;
import { listJobs } from &#39;../actions/jobActions&#39;;
import &#39;./HomeScreen.scss&#39;;
export default function HomeScreen() {
const dispatch = useDispatch();
const jobList = useSelector((state) =&gt; state.jobList);
const { loading, error, jobs } = jobList;
let [searchParams, setSearchParams] = useSearchParams();
const params = [];
searchParams.forEach((value, key) =&gt; {
params.push([key, value]);
});
const queryParams = new URLSearchParams(params);
const url = new URL(window.location.href);
window.history.pushState(null, null, url);
useEffect(() =&gt; {
dispatch(listJobs(queryParams));
console.log(jobs);
}, [dispatch]);
const addQuery = (key, value) =&gt; {
setSearchParams((prev) =&gt; [...prev.entries(), [key, value]]);
};
return (
&lt;&gt;
&lt;Filterbar /&gt;
&lt;ul&gt;
{jobs.map((job) =&gt; (
&lt;li className={job.featured ? &#39;post featured&#39; : &#39;post&#39;} key={job._id}&gt;
&lt;div className=&quot;post__img-container&quot;&gt;
&lt;img src={job.logo} alt=&quot;photosnap&quot; /&gt;
&lt;/div&gt;
&lt;div className=&quot;post__upper-container&quot;&gt;
&lt;div className=&quot;post__company-container&quot;&gt;
&lt;h2 className=&quot;post__company&quot;&gt;{job.company}&lt;/h2&gt;
{job.new &amp;&amp; &lt;span className=&quot;post__label new&quot;&gt;new!&lt;/span&gt;}
{job.featured &amp;&amp; (
&lt;span className=&quot;post__label featured&quot;&gt;featured&lt;/span&gt;
)}
&lt;/div&gt;
&lt;h3 className=&quot;post__job-title&quot;&gt;{job.position}&lt;/h3&gt;
&lt;div className=&quot;post__data&quot;&gt;
&lt;span className=&quot;post__date&quot;&gt;{job.postedAt}&lt;/span&gt;
&lt;div className=&quot;post__dot&quot;&gt;&lt;/div&gt;
&lt;span className=&quot;post__hours&quot;&gt;{job.contract}&lt;/span&gt;
&lt;div className=&quot;post__dot&quot;&gt;&lt;/div&gt;
&lt;span className=&quot;post__location&quot;&gt;{job.location}&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div className=&quot;post__lower-container&quot;&gt;
&lt;button
className=&quot;post__category&quot;
name=&quot;role&quot;
value={job.role}
onClick={(e) =&gt; addQuery(&#39;role&#39;, e.currentTarget.value)}
&gt;
&lt;span&gt;{job.role}&lt;/span&gt;
&lt;/button&gt;{&#39; &#39;}
&lt;button
className=&quot;post__category&quot;
value={job.level}
onClick={(e) =&gt; addQuery(&#39;level&#39;, e.currentTarget.value)}
&gt;
&lt;span&gt;{job.level}&lt;/span&gt;
&lt;/button&gt;
{job.languages.map((language) =&gt; (
&lt;button
className=&quot;post__category&quot;
name=&quot;language&quot;
value={language}
onClick={(e) =&gt; addQuery(&#39;languages&#39;, e.currentTarget.value)}
&gt;
&lt;span&gt;{language}&lt;/span&gt;
&lt;/button&gt;
))}
{job.tools.map((tool) =&gt; (
&lt;button
className=&quot;post__category&quot;
name=&quot;tool&quot;
value={tool}
onClick={(e) =&gt; addQuery(&#39;tools&#39;, e.currentTarget.value)}
&gt;
&lt;span&gt;{tool}&lt;/span&gt;
&lt;/button&gt;
))}
&lt;/div&gt;
&lt;/li&gt;
))}
&lt;/ul&gt;
&lt;/&gt;
);
}

jobActions.js

import axios from &#39;axios&#39;;
import {
JOB_LIST_REQUEST,
JOB_LIST_SUCCESS,
JOB_LIST_FAIL,
} from &#39;../constants/jobConstants&#39;;
export const listJobs = (queryParams) =&gt; async (dispatch) =&gt; {
try {
dispatch({ type: JOB_LIST_REQUEST });
console.log(queryParams);
const { data } = await axios.get(&#39;/api/jobs&#39;, { params: queryParams });
dispatch({
type: JOB_LIST_SUCCESS,
payload: data,
});
} catch (error) {
dispatch({
type: JOB_LIST_FAIL,
payload:
error.response &amp;&amp; error.response.data.message
? error.response.data.message
: error.message,
});
}
};

backend>controller>jobs.js

import ErrorResponse from &#39;../utils/errorResponse.js&#39;;
import asyncHandler from &#39;../middleware/async.js&#39;;
import Job from &#39;../models/Job.js&#39;;
// @desc Get all jobs
// @routes GET /api/jobs
// @access Public
const getJobs = asyncHandler(async (req, res, next) =&gt; {
// let query;
// copy req.query
const reqQuery = { ...req.query };
// create query string
let queryStr = JSON.stringify(reqQuery);
// create operators ($gt, $gte, etc)
queryStr = queryStr.replace(
/\b(gt|gte|lt|lte|in)\b/g,
(match) =&gt; `$${match}`
);
// Finding resource
const jobs = await Job.find(JSON.parse(queryStr));
console.log(jobs);
res.json(jobs);
});

答案1

得分: 0

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

useEffect(() => {
    dispatch(listJobs(queryParams));
  }, [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.

useEffect(() =&gt; {
dispatch(listJobs(queryParams));
}, [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:

确定