首页 > 解决方案 > 渲染道具组件抛出对象作为 React 子项无效

问题描述

我正在尝试制作自己的去抖动输入元素,我可以在其中发送我需要的任何输入组件,例如 textarea 和 input 并使其去抖动。我制作了一个如下所示的 debounceComponent:

import { useState, useCallback } from "react";
import debounce from "lodash.debounce";

const useDebounce = (callback, delay) => {
  const debouncedFn = useCallback(
    debounce((...args) => callback(...args), delay),
    [delay] // will recreate if delay changes
  );
  return debouncedFn;
};

function DebouncedInput(props) {
  const [value, setValue] = useState(props.initialValue);
  const debouncedSave = useDebounce(
    (nextValue) => props.onChange(nextValue),
    1000
  );

  const handleChange = (event) => {
    const { value: nextValue } = event.target;
    setValue(nextValue);
    debouncedSave(nextValue);
  };

  return props.renderProps({ ...props, handleChange, value });

  //return <textarea value={value} onChange={handleChange} rows={5} cols={50} />;
}

export default DebouncedInput;

这就是我使用它的方式:

 <DebouncedInput
    initialValue={value}
    onChange={handleChange}
    rows={5}
    cols={50}
    renderProps={(props) => <TextArea {...props} />}
  />

但是,如果我这样使用它,我会得到一个错误:

对象作为 React 子级无效(发现:对象与键 {dispatchConfig、_targetInst、_dispatchListeners、_dispatchInstances、nativeEvent、type、target、currentTarget、eventPhase、bubbles、cancelable、timeStamp、defaultPrevented、isTrusted、isDefaultPrevented、isPropagationStopped})。如果您打算渲染一组子项,请改用数组。

您可以在此处查看它的代码和框。我在这里做错了什么,我该如何解决?

标签: reactjs

解决方案


在您的DebouncedInput组件中更改 return 语句。

return props.renderProps({ ...props, handleChange, value });

return props.renderProps({ ...props, onChange: handleChange, value });
import { useState, useCallback } from "react";
import debounce from "lodash.debounce";

const useDebounce = (callback, delay) => {
  const debouncedFn = useCallback(
    debounce((...args) => callback(...args), delay),
    [delay] // will recreate if delay changes
  );
  return debouncedFn;
};

function DebouncedInput(props) {
  const [value, setValue] = useState(props.initialValue);
  const debouncedSave = useDebounce(
    (nextValue) => props.onChange(nextValue),
    1000
  );

  const handleChange = (event) => {
    const { value: nextValue } = event.target;
    setValue(nextValue);
    debouncedSave(nextValue);
  };

  return props.renderProps({ ...props, onChange: handleChange, value });

}

export default DebouncedInput;

此外,不要将所有道具传播到组件,而是仅传递与输入元素相关的道具。因此,在这种情况下,当调用组件props.renderProps({ ...props, onChange: handleChange, value })接收到的所有道具时,DebouncedInput都直接传递给inputorTextArea组件,这意味着renderProps也正在传递。但总的来说input,或者TextArea可能没有initialValue ,renderProps作为道具,那会引发警告。

为了不收到此类警告,有多种方法,以下是其中一种方法

  • 将所需DebouncedInput的道具和输入组件的道具作为rest参数传播
function DebouncedInput({initialValue, renderProps, onChange, ...rest}) {
  const [value, setValue] = useState(initialValue);
  const debouncedSave = useDebounce(
    (nextValue) => onChange(nextValue),
    1000
  );

  const handleChange = (event) => {
    const { value: nextValue } = event.target;
    setValue(nextValue);
    debouncedSave(nextValue);
  };

  return renderProps({ ...rest, onChange: handleChange, value });

}
  • 将所有与 input/TextArea 相关的道具传递到另一个对象中,如下所示。在这里,我传递了我想要作为输入组件的一部分发送的所有相关道具,我包装在里面inputProps并通过renderProps.
<DebouncedInput
    initialValue={value}
    onChange={handleChange}
    renderProps={(props) => <TextArea {...props} />}
    inputProps={{rows:5, cols:50}}
  />
function DebouncedInput(props) {
  const [value, setValue] = useState(props.initialValue);
  const debouncedSave = useDebounce(
    (nextValue) => props.onChange(nextValue),
    1000
  );

  const handleChange = (event) => {
    const { value: nextValue } = event.target;
    setValue(nextValue);
    debouncedSave(nextValue);
  };

  return props.renderProps({ ...props.inputProps, onChange: handleChange, value });

}
  • 由于您从同一个地方传递 theprops和 the ,因此您可以通过如下简单的方式进行操作component
 <DebouncedInput
    initialValue={value}
    onChange={handleChange}
    renderProps={(props) => <TextArea {...props} rows={5} cols={50}/>}
  />
function DebouncedInput(props) {
  const [value, setValue] = useState(props.initialValue);
  const debouncedSave = useDebounce(
    (nextValue) => props.onChange(nextValue),
    1000
  );

  const handleChange = (event) => {
    const { value: nextValue } = event.target;
    setValue(nextValue);
    debouncedSave(nextValue);
  };

  return props.renderProps({ onChange: handleChange, value });

}

推荐阅读