Как правильно управлять состоянием реакции для списка JSX.Elements - PullRequest
3 голосов
/ 17 октября 2019

Я использую реагирующие хуки для управления списком JSX.Elements. Однако после изменения элемента попытка его удаления приведет к непредвиденному поведению.

Я пытался использовать useReducer, удалить по индексу и т. Д., Но по-прежнему произошел неожиданный обновленный результат.

FolderPage. tsx

import React, { useState, useEffect } from 'react';
import { Button, Box, Grid } from 'grommet';
import { Add, Close } from 'grommet-icons';

import { Files } from '../Component/Files/Files';
import { ePub } from '../extension/ePub/ePub';

interface Props {}

export const FolderPage: React.FC<Props> = () => {
  const [state, setState] = useState([<Files openFileHandlers={[ePub]} />]);

  const newFolderPanel = () => setState(prev => prev.concat(<Files openFileHandlers={[ePub]} />));

  const removePanel = (panel: JSX.Element) => setState(prevState => prevState.filter(s => s !== panel));

  return (
    <div>
      <Box align="start" pad="xsmall">
        <Button icon={<Add />} label="New Folder Panel" onClick={newFolderPanel} primary />
      </Box>
      {state.map((s, index) => (
        <Grid key={index}>
          <Box align="end">
            <Button
              icon={<Close color="white" style={{ backgroundColor: 'red', borderRadius: '50%', padding: '.25rem' }} />}
              type="button"
              onClick={() => removePanel(s)}
            />
          </Box>
          {s}
        </Grid>
      ))}
    </div>
  );
};

Например, при использовании: enter image description here

Что я должен изменить в своем коде, чтобы мой клик на удаление удалял соответствующий элемент?

1 Ответ

0 голосов
/ 31 октября 2019

Есть способ обойти это. Для каждого элемента в массиве. Вместо непосредственного хранения элемента, сохраните его как {id: yourAssignedNumber, content: item}.

Таким образом, вы можете контролировать идентификатор и удалить его, сравнивая только идентификатор. Таким образом, он будет работать правильно.

import React, { useState, useRef } from 'react';
import { Button, Row, Col } from 'antd';

import { Files } from '../Components/Files/Files';
import { fileHandler } from '../model/fileHandler';

interface Props {
  fileHandlers?: fileHandler[];
}

export const FolderPage: React.FC<Props> = ({ fileHandlers }) => {
  const [state, setState] = useState([{ key: -1, content: <Files fileHandlers={fileHandlers} /> }]);
  const key = useRef(0);

  const newFolderPanel = () =>
    setState(prev =>
      prev.concat({
        key: key.current++,
        content: <Files fileHandlers={fileHandlers} />
      })
    );

  const removePanel = (key: number) => setState(prevState => prevState.filter(s => s.key !== key));

  return (
    <Row>
      <Button type="primary" icon="plus" onClick={newFolderPanel} style={{ margin: '.75rem' }}>
        New Foldr Panel
      </Button>
      {state.map(({ key, content }) => (
        <Col key={key}>
          <div
            style={{
              background: '#75ff8133',
              display: 'grid',
              justifyItems: 'end',
              padding: '.5rem 1rem'
            }}>
            <Button onClick={() => removePanel(key)} icon="close" type="danger" shape="circle" />
          </div>
          {content}
        </Col>
      ))}
    </Row>
  );
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...