React.memo()重置状态

时间:2019-07-11 10:56:03

标签: javascript reactjs

我有一些输入是从对象数组中渲染的。

当我输入一个输入时,我会在数组上映射,找到相应的对象并设置输入值。

问题:在一个输入中键入一些字符,更改输入,键入字符。重复此步骤,观察先前的输入已清除,有时某些输入中会出现一些随机字符。

是什么原因导致这种行为?

如果我从SearchBar中删除了React.memo(),问题就不会再出现了。

我需要做什么才能使其与React.memo()一起使用。

const shouldSkipComponentUpdate = (prevProps, props) =>
prevProps.value === props.value;

const SearchBar = React.memo((props) => {
  const { label, width, hasSearch, handleSearchChange, value } = props;
    return (
      <div width={width} style = { { margin: "15px", display: "inline" } }>
        {label}
        {hasSearch && (
          <SearchInput
            onChange={handleSearchChange}
            value={value}
            label={label}
          />
        )}
      </div>
    );
  }, (prevProps, props) => shouldSkipComponentUpdate(prevProps, props));


function DevicesContainer() {
  const [searchBoxes, setSearchBoxes] = React.useState(() => {
    return [
      {
        id: 1,
        label: '',
        width: '5%',
        hasSearch: false,
        value: ''
      },
      {
        id: 2,
        label: 'ID',
        width: '5%',
        value: '',
        hasSearch: false
      },
      {
        id: 3,
        width: '10%',
        label: 'Name',
        value: '',
        hasSearch: true
      },
      {
        id: 4,
        width: '10%',
        label: 'Owner',
        value: '',
        hasSearch: true
      },
      {
        id: 5,
        width: '7%',
        label: 'Availability',
        value: '',
        hasSearch: false
      },
      {
        id: 6,
        width: '10%',
        label: 'Location',
        value: '',
        hasSearch: true
      },
      {
        id: 7,
        width: '20%',
        label: 'Environment',
        value: '',
        hasSearch: true
      },
      {
        id: 8,
        width: '10%',
        label: 'Firmware',
        value: '',
        hasSearch: true
      },
    ];
  });
  function handleSearchChange(event, label) {
    const {
      target: { value }
    } = event;
    const updated = searchBoxes.map(elem => {
      if (elem.label === label) {
        return { ...elem, value };
      }
      return elem;
    });
    setSearchBoxes(updated);
  }
  return (
    <main>
      <SearchBars
        searchBars={searchBoxes}
        handleSearchChange={handleSearchChange}
        />
    </main>
  );
}

function SearchBars(props) {
  const { searchBars, handleSearchChange } = props;
  return (
    <div style={ { margin: '20px' } }>
      {searchBars.map(elem => (
        <SearchBar
          key={elem.id}
          label={elem.label}
          width={elem.width}
          hasSearch={elem.hasSearch}
          value={elem.value}
          handleSearchChange={handleSearchChange}
          />
      ))}
    </div>
  );
}

function SearchInput(props) {
  const { onChange, value, label } = props;
  return (
    <input
      type="search"
      value={value}
      placeholder="Search"
      onChange={event => onChange(event, label)}
      />
  );
}

  ReactDOM.render(
    <DevicesContainer />,
    document.getElementById('root')
  );


codepen链接https://codepen.io/Apoptotic/pen/ZdPpQG

1 个答案:

答案 0 :(得分:0)

您可以更改handleSearchChange()功能。请参阅setState行为上的docs。您可能还注意到,该函数异步运行。我只是将映射功能移到了setSearchBox更新句柄中,以将数据应用于先前的状态。

  function handleSearchChange(event, label) {
    const {
      target: { value }
    } = event;


    setSearchBoxes((prevSearchBoxes) => {
      let s = [...prevSearchBoxes];
      let updated = s.map(elem => {
        if (elem.label === label) {
          return { ...elem, value };
        }
        return elem;
      });
      return updated;
    });
  }

另外请参阅React Docs中的以下说明。

  

与在类组件中找到的setState方法不同,useState可以   不会自动合并更新对象。您可以复制此   通过将功能更新程序形式与对象传播相结合来实现行为   语法:

setState(prevState => {
  // Object.assign would also work
  return {...prevState, ...updatedValues};
});
  

另一个选项是useReducer,它更适合于管理状态   包含多个子值的对象。