首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将类组件重构为具有上下文的功能组件

将类组件重构为具有上下文的功能组件
EN

Stack Overflow用户
提问于 2019-11-09 03:07:09
回答 1查看 203关注 0票数 0

我正在尝试将一些代码从类重构到功能组件,以便与我的应用程序的其余部分保持一致。这些类正在更新状态,在应用程序中,它们需要更新一个名为cardContext.js的上下文。我需要做的第一件事是将类重写为函数式组件,以便更新上下文而不是内部状态。

我的站点大部分是通过带有钩子的功能组件工作的,我正在使用上下文。

每个上下文有3个文件;

  • ExampleState.js
  • exampleContext.js
  • exampleReducer.js

到目前为止,应用程序的代码都在这里https://codesandbox.io/s/infshot-978on?fontsize=14) (预览不起作用,因为我不认为codesandbox可以完成完整的堆栈应用程序,但是您可以通过client> src> components>card和client> src> components>context>card看到相关的代码。

我正在尝试将一些被编码为类的组件集成到我的应用程序中,以同样的方式工作,这样我就可以集成它了。首先,我需要重构这些组件,使它们成为功能组件,并以与应用程序其他部分相同的形式使用上下文。新组件使用的是一个名为React的框架,我使用教程创建了它们,它创建了类组件。

我被困在如何重构他们的问题上。

我试图重构的第一个文件如下

代码语言:javascript
复制
// files in context/dnd editor are placeholders
import React from 'react';
import ReactDOM from 'react-dom';
import '@atlaskit/css-reset';
import 'materialize-css/dist/css/materialize.min.css';
import '../../index.css'

import styled from 'styled-components';
import { DragDropContext } from 'react-beautiful-dnd';
import initialData from './initialData';
import Column from './column';


const Container = styled.div`
  display: flex;
`;

export default class dndEditor extends React.Component {
  state = initialData;

  onDragEnd = result => {
    document.body.style.color = 'inherit';
    const { destination, source, draggableId } = result;
    if (!destination) {
      return;
    }
    if (
      destination.droppableId === source.droppableId &&
      destination.index === source.index
    ) {
      return;
    }

    const start = this.state.columns[source.droppableId];
    const finish = this.state.columns[destination.droppableId];

    if (start === finish) {
      const newTaskIds = Array.from(start.taskIds);
      newTaskIds.splice(source.index, 1);
      newTaskIds.splice(destination.index, 0, draggableId);

      const newColumn = {
        ...start,
        taskIds: newTaskIds
      };
      const newState = {
        ...this.state,
        columns: {
          ...this.state.columns,
          [newColumn.id]: newColumn
        }
      };
      this.setState(newState);
      return;
    }
    //Start and finnish columns are different
    const startTaskIds = Array.from(start.taskIds);
    startTaskIds.splice(source.index, 1);
    const newStart = {
      ...start,
      taskIds: startTaskIds
    };

    const finishTaskIds = Array.from(finish.taskIds);
    finishTaskIds.splice(source.index, 0, draggableId);
    const newFinish = {
      ...finish,
      taskIds: finishTaskIds
    };

    const newState = {
      ...this.state,
      columns: {
        ...this.state.columns,
        [newStart.id]: newStart,
        [newFinish.id]: newFinish
      }
    };
    this.setState(newState);
    return;
  };

  render() {
    return (
      <Container>
        <DragDropContext onDragEnd={this.onDragEnd}>
          {this.state.columnOrder.map(columnId => {
            const column = this.state.columns[columnId];
            const tasks = column.taskIds.map(
              taskId => this.state.tasks[taskId]
            );

            return <Column key={column.id} column={column} tasks={tasks} />;
          })}
        </DragDropContext>

      </Container>
    );
  }
}

下面是initialData.js文件(初始状态)

代码语言:javascript
复制
const InitialData = {
  tasks: {
    'task-1': {
      id: 'task-1',
      content: 'Take out the trash and another thing also'
    },
    'task-2': { id: 'task-2', content: 'another link' },
    'task-3': { id: 'task-3', content: 'clear desk' },
    'task-4': { id: 'task-4', content: 'do pushups' }
  },
  columns: {
    'column-1': {
      id: 'column-1',
      title: 'FACTS',
      taskIds: ['task-2', 'task-3', 'task-4']
    },
    'column-2': {
      id: 'column-2',
      title: 'PROS',
      taskIds: ['task-1']
    },
    'column-3': {
      id: 'column-3',
      title: 'CONS',
      taskIds: []
    }
  },
  columnOrder: ['column-1', 'column-2', 'column-3']
};
export default InitialData;

(我想重构的所有文件都在下面的函数代码框中) https://codesandbox.io/s/react-beautiful-dnd-trello-example-ohxsi?fontsize=14

EN

回答 1

Stack Overflow用户

发布于 2019-11-10 13:11:21

我不明白什么是真正的挑战。将setState + this.state重构为useState应该是可行的。这个组件提供的是上下文,而不是消费。因此,与上下文相关的一切都保持着现在的样子。

代码语言:javascript
复制
export default function DndEditor() {
  const [state, setState] = useState(initialData);

  onDragEnd = result => {
    document.body.style.color = 'inherit';
    const { destination, source, draggableId } = result;
    if (!destination) {
      return;
    }
    if (
      destination.droppableId === source.droppableId &&
      destination.index === source.index
    ) {
      return;
    }

    const start = state.columns[source.droppableId];
    const finish = state.columns[destination.droppableId];

    if (start === finish) {
      const newTaskIds = Array.from(start.taskIds);
      newTaskIds.splice(source.index, 1);
      newTaskIds.splice(destination.index, 0, draggableId);

      const newColumn = {
        ...start,
        taskIds: newTaskIds
      };
      const newState = {
        ...this.state,
        columns: {
          ...state.columns,
          [newColumn.id]: newColumn
        }
      };
      setState(newState);
      return;
    }
    //Start and finnish columns are different
    const startTaskIds = Array.from(start.taskIds);
    startTaskIds.splice(source.index, 1);
    const newStart = {
      ...start,
      taskIds: startTaskIds
    };

    const finishTaskIds = Array.from(finish.taskIds);
    finishTaskIds.splice(source.index, 0, draggableId);
    const newFinish = {
      ...finish,
      taskIds: finishTaskIds
    };

    const newState = {
      ...state,
      columns: {
        ...state.columns,
        [newStart.id]: newStart,
        [newFinish.id]: newFinish
      }
    };
    setState(newState);
    return;
  };

  return (
    <Container>
      <DragDropContext onDragEnd={onDragEnd}>
        {state.columnOrder.map(columnId => {
          const column = state.columns[columnId];
          const tasks = column.taskIds.map(
            taskId => state.tasks[taskId]
          );
           return <Column key={column.id} column={column} tasks={tasks} />;
        })}
      </DragDropContext>
     </Container>
  );
}

此外,您可能希望将state拆分为独立的

代码语言:javascript
复制
const [columns, setColumns] = useState(initialData.columns);
const [tasks, setTasks] = useState(initialData.tasks);

为了获得更好的可读性,但是首先尝试一下,[state, setState]将是最简单的重构方法。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58776049

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档