繁体   English   中英

当数据被继承时,使用 React-Redux 从减速器而不是从根 state 更改 state

[英]Change state from reducer not from root state using React-Redux when data is inherited

下午好。 我正在使用 react-redux 编写应用程序并面临两难境地。 我已经重新思考了好几次,无法选择如何正确方便地组织项目和数据结构。 通过继承或组合数据来设计数据。 我最初是沿着作曲的道路走的,但我意识到当存在一对一的关系时很不方便。 我决定将其更改为 inheritance,因为从数据组织的角度来看这似乎是合乎逻辑的,但是reducers有很大的困难,更准确地说,我很困惑,它原来是一个单根reducer ,有很多actionTypes键。 我记得性能方面,当元素从共同祖先那里继承数据链时,这是非常糟糕的。 然而我选择了这条路,我有一个问题:请告诉我是否可以为每个级别的嵌套数据拆分成几个reducers 例子

onst initState: IPages = {
  idActive: 0,
  pages: [
    {
      id: 1,
      title: `Tab #1`,
      workspace: {
        idActiveDraggableElements: [],
        idActiveLines: [],
        attributes: {
          height: string,
          width: string,
          viewBox: [0, 0, 5000, 5000]
        },
        draggableElements: [], // more data
        lines: [],  // more data
      }
    },
  ]
}

减速器:

export function pagesReducer(
  state: IPages = initState,
  action: IPageActionTypes
) {
  switch (action.type) {
    case "ADD_PAGE":
      let uniqId = getUniqKeyIdOfArrayList(state.pages);
      return {
      ...state,
      pages: state.pages.concat({id:uniqId, title:`Вкладка - ${uniqId}`})
    }
    case "REMOVE_PAGE": return {
      ...state,
      pages: state.pages.filter(item => item.id !== action.id)
    }
    case "CHOSE_PAGE": return {
      ...state,
      idActive: action.id
    }
    case "RENAME_PAGE":
      let indexPage = state.pages.findIndex(item => item.id === action.id);
      state.pages[indexPage].title = action.title;
      return {
      ...state
      }

      // ===================
      // LONG LIST WHAT BAD...
      // It's a bad idea to add editing to the `workspace` field and then `draggableElements`. `lines` 
      // ... but I understand that this will happen, because I don't know if there is another way.
    default:
      return state
  }
}

我可以在不更新整个应用程序 state 的情况下编辑“工作区”节点吗?

谢谢你的帮助。

对于一对一关系的数据建模方面,您可以选择通过 id 引用或嵌入数据。 这取决于您的查询模式。

在嵌入的情况下,您可以使用memoized selectors

理想情况下,由于您有一个idActive ,请将您的pages数据结构更新为 object 而不是列表。

像这样:

{
  pages: {
    '1': {
       workspace: { ... },  
    }
  }
}

然后对于您的减速器,将其视为切片树(或嵌套属性)。 然后你的减速器看起来像:

function workspaceReducer(state, action) {
  // TODO
}

function pagesReducer(state, action) {
  switch (action.type) {
    case 'UPDATE_WORKSPACE': {
      const { id } = action;
      const page = Object.assign({}, state.pages[id]);
      return {
        ...state,
        pages: {
          ...state.pages,
          [id]: {
             ...page,
             workspace: workspaceReducer(page.workspace, action)
          }
        }
      }
    }
  }
} 

然后为了防止不必要的重新渲染,使用记忆选择器,就像:

import { createSelector } from 'reselect';

const pages = state => state.pages;
const activePage = state => state.idActive;

const getActivePage = createSelector(
  activePage,
  pages,
  (id, pages) => pages[id]
);

const getWorkspace = createSelector(
  getActivePage,
  page => page.workspace
);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM