You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Select更新其他状态(如remarks)时总是重渲染,如何解决?

Fix Unwanted Re-renders of React Select When Updating Remarks Input

Great question! This is a super common React performance hiccup—when your parent component re-renders (thanks to the remarks state updating as you type), all child components (including your React Select) re-render too, even if their props haven’t changed. Let’s break down how to fix this step by step.

Why This Happens

Every time you type in the remarks textarea, the remarks state updates, triggering a full re-render of the parent component. By default, React re-renders all child components during a parent re-render, no matter if their props are the same or not. The problem here is that your Select component is receiving props (like the onChange function or options array) that get recreated on every render, so React sees them as "new" and re-renders the Select unnecessarily.

Solution 1: Use React.memo with Cached Props

We can memoize the React Select component using React.memo so it only re-renders when its actual props change. To make this work, we need to ensure the props passed to Select have stable references between renders.

Here’s how to tweak your code:

  1. Cache the onChange function with useCallback: This keeps the function reference consistent unless its dependencies change.
  2. Cache the options array with useMemo: Prevents creating a new array reference on every render if the options don’t change.
  3. Wrap the Select component with React.memo: Tells React to skip re-rendering the Select if props are identical to the last render.
const [expense_currency, setExpenseCurrency] = React.useState(expense_claim.expense_currency);
const [remarks, setRemarks] = React.useState(expense_claim.remarks);

// Cache the onChange function - setExpenseCurrency is stable, so no extra re-renders here
const handleCurrencyChange = React.useCallback(selected => {
  setExpenseCurrency(selected.value);
}, [setExpenseCurrency]);

// Cache options array - add select_currency to dependencies if it's dynamic (e.g., from props)
const memoizedCurrencyOptions = React.useMemo(() => select_currency, []);

// Create a memoized version of the Select component
const MemoizedSelect = React.memo(Select);

// ...

return (
  // ...
  <div className="form-group row p-0 col-sm-12 col-md-6">
    <label className="text-nowrap col-form-label col-sm-4">Currency</label>
    <div className="col-sm-8 p-0" title={expense_currency}>
      <MemoizedSelect
        className="select2"
        placeholder="Select Currency"
        isDisabled={false}
        isClearable={true}
        value={expense_currency}
        options={memoizedCurrencyOptions}
        onChange={handleCurrencyChange}
      />
    </div>
  </div>
  {/* Remarks textarea stays the same */}
)

Solution 2: Extract the Select into a Separate Memoized Component

Another clean approach is to move the React Select into its own standalone component wrapped with React.memo. This isolates the Select from the parent’s re-renders unless its specific props change.

// Separate memoized component for currency selection
const CurrencySelect = React.memo(({ value, onChange, options }) => {
  return (
    <Select
      className="select2"
      placeholder="Select Currency"
      isDisabled={false}
      isClearable={true}
      value={value}
      options={options}
      onChange={onChange}
    />
  );
});

// In your parent component:
const [expense_currency, setExpenseCurrency] = React.useState(expense_claim.expense_currency);
const [remarks, setRemarks] = React.useState(expense_claim.remarks);

const handleCurrencyChange = React.useCallback(selected => {
  setExpenseCurrency(selected.value);
}, [setExpenseCurrency]);

const memoizedCurrencyOptions = React.useMemo(() => select_currency, []);

// ...

return (
  // ...
  <div className="form-group row p-0 col-sm-12 col-md-6">
    <label className="text-nowrap col-form-label col-sm-4">Currency</label>
    <div className="col-sm-8 p-0" title={expense_currency}>
      <CurrencySelect
        value={expense_currency}
        onChange={handleCurrencyChange}
        options={memoizedCurrencyOptions}
      />
    </div>
  </div>
)

Quick Notes

  • If select_currency is dynamic (e.g., comes from parent props or state), add it to the useMemo dependency array so options update when needed.
  • React.memo does a shallow comparison of props. If you’re passing complex objects as props, you can add a custom comparison function as the second argument to React.memo, but that’s rarely necessary here.
  • setExpenseCurrency is guaranteed to be stable across renders by React, so it’s safe to include in the useCallback dependencies without causing extra re-renders.

内容的提问来源于stack exchange,提问作者Rio A.P

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 09:01:57