React 组件在选项卡之间来回移动时加载数据两次

React component loads data twice on moving back-and-forth between tabs

出于某种原因,我的 React 组件在转到另一个选项卡并再次返回时似乎记住了它的旧状态,而不是完全重新加载。

基本上,当我单击导航栏中的“创建”选项卡并返回“看板”选项卡时,数据会填充两次而不是一次,请参见下图。当返回时,Board 组件 this.state 每个 taskIds 都有两个,就好像组件状态在再次加载时仍然具有初始页面加载的数据一样。我有一个像这样的 React 组件:

const columnOrder = ['todo', 'in-progress', 'in-review', 'done']
const EMPTY_COLUMNS = {
  'todo': {
    id: 'todo',
    title: 'TODO',
    taskIds: []
  },
  'in-progress': {
    id: 'in-progress',
    title: 'In Progress',
    taskIds: [],
  },
  'in-review': {
    id: 'in-review',
    title: 'In Review',
    taskIds: []
  },
  'done': {
    id: 'done',
    title: 'Done',
    taskIds: []
  }
};

export class Board extends Component {
   constructor(props) {
        super(props);
        this.onLoadEpic = this.onLoadEpic.bind(this);
        this.state = {
            columnOrder: columnOrder,
            columns: {
                'in-progress': {
                    id: 'in-progress',
                    title: 'In Progress',
                    taskIds: [],
                },
            // ...more columns similar to above
            },
        };
    
    // Load state data on mount
    componentDidMount() {
        loadEpic(arg1, arg2);
    }

    // Async function loading items from DB and formatting into useful columns
    async loadEpic(arg1, arg2) {
        axios.get(...)
            .then((response) => {
                let data = response.data;
                let newTasks = {};
                let newColumns = EMPTY_COLUMNS;
                
                data.taskItems.forEach(function(item) {
                   let id = item.id.toString();
                   newColumns[item.status]["taskIds"].push(id);
                   newTasks[id] = {
                       ...item,
                       id: id
                   }
                });
                this.setState({
                    tasks: newTasks,
                    columns: newColumns
                });
            })
    }

    render() {
        // Prints ["7"] on initial load and ["7", "7"] after going back and forth
        console.log(this.state.columns["in-progress"].taskIds);
        return (
          // Simplified, but this is the main idea
          <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>
        )
    }

}

和一个 App.js 路由如下所示:

export default class App extends Component {
  static displayName = App.name;

  render () {
    return (
      <Layout>
        <Route exact path='/' component={Board} />
        <Route exact path='/create' component={Create} />
      </Layout>
    );
  }
}

好吧,我想通了:是 EMPTY_COLUMNS 常量出问题了。当组件被重新渲染时,相同的 EMPTY_COLUMNS 对象被引用 - 所以常量被附加到。相反,我应该复制空列:

// Before - same object is being appended to, doesn't work
let newColumns = EMPTY_COLUMNS;
// After - create a deep copy of the constant, does work
let newColumns = JSON.parse(JSON.stringify(EMPTY_COLUMNS));