未使用 useState 钩子设置状态 | ReactJS

时间:2021-02-25 10:42:46

标签: reactjs redux react-hooks

我有一个组件,我将 API 响应存储在 responseArray 中,我正在使用此 responseArray 使用钩子初始化 matchFundResults 状态。接下来,我尝试使用 matchFundResults 作为依赖项运行 useEffect,但 matchFundResults 始终为空白,而我在 responseArray 中有值。这应该如何解决?

const MatchFundModal = ({ row, val }) => {
  let rightBody;
  const dispatch = useDispatch();
  const selectedRows = useSelector((state) => state.pcPerformance.processor.checkedRows.selectedRows || []);
  const responseArray = useSelector((state) => state.pcPerformance.processor.fundAliases);
  const [showMatchFundModal, setshowMatchFundModal] = useState(val);
  const [matchFundResults, setMatchFundResults] = useState(responseArray);
  
  const [activeRowData, setActiveRowData] = useState({ Id: null, FundName: null, SourceId: null });
  
  const [selectedMatchFund, setSelectedMatchFund] = useState();
  const [searchFieldVal, setSearchFieldVal] = useState();

  if (!activeRowData.Id) {
    const firstRow = selectedRows.length > 0 && selectedRows[0];
    setActiveRowData({ Id: firstRow.Id, FundName: firstRow.FundName, SourceId: firstRow.SourceId });
    //dispatch(getFundNameAliasMatch(firstRow.FundName, firstRow.SourceId));
  }
  useEffect(() => {
    dispatch(getFundNameAliasMatch(activeRowData.FundName, activeRowData.SourceId));
  }, [activeRowData.Id]);
  
  console.log('Helloworld responseArray', responseArray);
  console.log('Helloworld matchFundResults', matchFundResults);
  useEffect(() => {
    rightBody = matchFundResults**.map((item) => {
      return (
        <li key={item.FundId}>
          <input
            type="radio"
            value={item.FundId}
            name="action-radio"
            id={`action-radio-${item.FundId}-${item.SourceId}`}
            onClick={(e) => handleRadioButtonClick(e)}
          />
          <span>{item.FundName}</span>
          <br />
          <span className="searchFundID">#{item.FundId}</span>
        </li>
      );
    });
  }, [matchFundResults, activeRowData.Id]);

  const matchFundBody = (
    <div className="matchFundModal grid">
      <p className="matchFundModal__header 12">Match or add</p>
      <div className="matchFundModal__body 12">
        <div className="matchFundModal__body__right 6">
          <p id="possibleMatchText">Possible matches</p>
          <ul>{rightBody}</ul>
        </div>
      </div>
      <div className="matchFundModal__footer 12">
        <button className="matchFundModal__footer__button">Match Selected</button>
      </div>
    </div>
  );
  return (
    <Fragment>
      <Modal
        isOpen={showMatchFundModal}
        bodyContent={matchFundBody}
        showHeader={false}
        handleOnModalToggleFunction={hideModal}
        handleOnModalPrimaryButtonClick={onPrimaryButtonClick}
        handleOnModalSecondaryButtonClick={hideModal}
        primaryButtonText={'Match Fund'}
        centered={true}
        size="sm"
        hideFooterButtons={true}
        modalClasses="matchFundModal"
        showFooter={false}
      />
    </Fragment>
  );
};

export default MatchFundModal;```
[![enter image description here][1]][1]


  [1]: https://i.stack.imgur.com/HxIv4.png

1 个答案:

答案 0 :(得分:1)

我不知道您为什么要将 responseArray 复制到 matchFundResults 而不是直接使用 responseArray 但是当 responseArray 更改时您从不使用 setMatchFundResults 所以您只在最初设置它并且那时 responseArray 可能是一个空数组。您可以执行以下操作:

const responseArray = useSelector((state) =>
  state.pcPerformance.processor.fundAliases);
const [matchFundResults, setMatchFundResults] = useState(responseArray);
//every time responseArray changes you need to set matchFundResults
useEffect(()=>setMatchFundResults(responseArray),[responseArray])

但最好不要将 redux 状态复制到本地状态,而是直接使用 redux 状态。

您的评论表明您拥有处于 redux 状态的所有数据并且想要过滤数据(您将 redux 状态复制到本地状态的原因)。您可以通过以下方式使用选择器做到这一点:

const { Provider, useSelector } = ReactRedux;
const { createStore } = Redux;
const { createSelector } = Reselect;
const { useState, useMemo } = React;

const initialState = {
  data: [
    'hello world',
    'hello redux',
    'hello react',
    'goodbye jquery',
  ],
};
const reducer = (state) => state;
//selectors
const selectData = (state) => state.data;
const createSelectFilteredData = (filter) =>
  createSelector([selectData], (data) =>
    data.filter((item) =>
      item.toLowerCase().includes(filter.toLowerCase())
    )
  );
//creating store with redux dev tools
const store = createStore(reducer, initialState);
const App = () => {
  const [filter, setFilter] = useState('');
  const selectFilteredData = useMemo(
    () => createSelectFilteredData(filter),
    [filter]
  );
  const filteredData = useSelector(selectFilteredData);
  return (
    <div>
      <label>
        filter:
        <input
          type="text"
          value={filter}
          onChange={(e) => setFilter(e.target.value)}
        />
      </label>
      <div>
        filtered data:
        <pre>
          {JSON.stringify(filteredData, undefined, 2)}
        </pre>
      </div>
    </div>
  );
};

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/reselect/4.0.0/reselect.min.js"></script>
<div id="root"></div>