1

更新基于 Jayce444 的评论。我将计时器设置在组件之外,这很有帮助。全局变量是最好的主意吗?

let globalTimer = null;
const setSlidingTimer = (timer) => {
  globalTimer = timer;
};

const SearchJobs = (props) => {
  useEffect(() => console.log("<SearchJobs /> rendered"));

const [sliderValue, setSliderValue] = useState(20);

const sliderChangeHandler = (newValue) => {
    clearTimeout(globalTimer);
    const timer = setTimeout(setSliderValue, 300, newValue);
    setSlidingTimer(timer);
  };

原帖:

我的 React 应用程序由于父组件的过多重新渲染而导致性能下降,因为它的子组件(主要是滑块)在更改其值时过于频繁地更改状态。

我的想法(参见sliderChangeHandler)是在更新滑块的状态值之前等待300毫秒以减少重新渲染的数量。不知何故,这还行不通。有没有人可以帮助我特别是滑块并将类似的想法应用于输入框?就像在更新状态之前等待 300 毫秒一样。如果用户再次键入或滑动,请重置 300ms 计时器

这是父代码

import React, { useEffect, useState } from "react";

import Col from "react-bootstrap/Col";
import Button from "react-bootstrap/Button";
import InputGroup from "react-bootstrap/InputGroup";
import FormControl from "react-bootstrap/FormControl";

import Slider from "../UI/Slider/Slider";

const SearchJobs = (props) => {
  useEffect(() => console.log("<SearchJobs /> rendered"));

  const [sliderValue, setSliderValue] = useState(20);
  const [address, setAddress] = useState("");
  const [slidingTimeout, setSlidingTimeout] = useState("");

  const sliderChangeHandler = (event, newValue) => {
    clearTimeout(slidingTimeout);
    const timer = setTimeout(setSliderValue, 300, newValue);
    setSlidingTimeout(timer);
  };

  return (
    <>
      <Col xs={12} md={7}>
        <InputGroup className="mb-3">
          <InputGroup.Prepend>
            <InputGroup.Text id="inputGroup-sizing-default">
              Adresse
            </InputGroup.Text>
          </InputGroup.Prepend>
          <FormControl
            aria-label="Address"
            aria-describedby="inputGroup-sizing-default"
            placeholder="myAddress"
            value={address}
            onChange={(event) => setAddress(event.target.value)}
          />
        </InputGroup>
      </Col>
      <Col xs={12} md={5}>
        <Slider value={sliderValue} change={sliderChangeHandler} />
      </Col>
    </>
  );
};

export default SearchJobs;

这是滑块组件:

import React from "react";
import Typography from "@material-ui/core/Typography";
import Slider from "@material-ui/core/Slider";

const SliderComponent = (props) => {
  const marks = [
    {
      value: 0,
      label: "0 km",
    },

    {
      value: 50,
      label: "50 km",
    },
  ];

  function valuetext(value) {
    return `${value} km`;
  }

  return (
    <div className="ml-3 mr-3">
      <Typography id="discrete-slider-always" gutterBottom>
        Radius
      </Typography>
      <Slider
        defaultValue={20}
        value={props.sliderValue}
        onChange={(event, newValue) => props.change(event, newValue)}
        getAriaValueText={valuetext}
        aria-labelledby="discrete-slider-always"
        step={0.1}
        min={0}
        max={50}
        marks={marks}
        valueLabelDisplay="on"
      />
    </div>
  );
};

export default SliderComponent;

4

1 回答 1

1

您可以使用通用的去抖动功能,例如:

const debounce = (inputFun, milliseconds) => {
  let timeout;

  return (...args) => {
    if(!timeout) {
      inputFun(...args);

      timeout = setTimeout(
        () => ( timeout = undefined ), 
        milliseconds
      );
    }
  };
};

然后你创建一个sliderChangeHandler像这样的去抖:

const sliderChangeHandler = debounce(event => {
    setSliderValue(event.target.value);
}, 300);

你可能想调整sliderChangeHandler(不知道为什么你有eventand newValue)的参数来满足你的要求。

于 2021-01-27T00:15:27.037 回答