编程语言
首页 > 编程语言> > javascript – ReactJS – 提升状态与保持本地状态

javascript – ReactJS – 提升状态与保持本地状态

作者:互联网

在我的公司,我们正在将Web应用程序的前端迁移到ReactJS.
我们正在使用create-react-app(更新到v16),没有Redux.
现在我停留在一个页面上,可以通过以下图像简化结构:

Page structure

在MainContainer的componentDidMount()方法中,使用相同的后端请求检索由三个组件(SearchableList,SelectableList和Map)显示的数据.然后,此请求的结果将存储在MainContainer的状态中,并且具有或多或少的结构:

state.allData = {
  left: {
    data: [ ... ]
  },
  right: {
    data: [ ... ],
    pins: [ ... ]
  }
}

LeftContainer从MainContainer接收作为prop.allData.left的prop,并将props.left.data传递给SearchableList,再次作为prop.

RightContainer从MainContainer接收作为prop.allData.right的prop,并将props.right.data传递给SelectableList,将props.right.pins传递给Map.

SelectableList显示一个复选框以允许对其项目执行操作.每当在SelectableList组件的项目上发生动作时,它可能对Map引脚有副作用.

我决定在RightContainer状态下存储一个列表,该列表保留SelectableList显示的所有项目ID;此列表作为道具传递给SelectableList和Map.然后我向SelectableList传递一个回调函数,无论何时进行选择都会更新RightContainer中的id列表;新的道具到达SelectableList和Map,因此在两个组件中调用render().

它工作正常并有助于保持RightContainer中SelectableList和Map可能发生的一切,但我问这是否适用于提升状态和单一来源的概念.

作为可行的替代方案,我想到将一个_selected属性添加到MainContainer中state.right.data中的每个项目,并将select回调三个级别传递给SelectableList,处理MainContainer中的所有可能操作.但是一旦选择事件发生,这将最终强制加载LeftContainer和RightContainer,引入了像shouldComponentUpdate()这样的逻辑实现的需要,以避免无用的render(),特别是在LeftContainer中.

从架构和性能的角度来看,哪个/可能是优化此页面的最佳解决方案?

下面是我的组件摘录,以帮助您了解情况.

MainContainer.js

class MainContainer extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      allData: {}
    };
  }

  componentDidMount() {
    fetch( ... )
      .then((res) => {
        this.setState({
          allData: res
        });
      });
  }

  render() {
    return (
      <div className="main-container">
        <LeftContainer left={state.allData.left} />
        <RightContainer right={state.allData.right} />
      </div>
    );
  }
}

export default MainContainer;

RightContainer.js

class RightContainer extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      selectedItems: [ ... ]
    };
  }

  onDataSelection(e) {
    const itemId = e.target.id;
    // ... handle itemId and selectedItems ...
  }

  render() {
    return (
      <div className="main-container">
        <SelectableList
          data={props.right.data}
          onDataSelection={e => this.onDataSelection(e)}
          selectedItems={this.state.selectedItems}
        />
        <Map
          pins={props.right.pins}
          selectedItems={this.state.selectedItems}
        />
      </div>
    );
  }
}

export default RightContainer;

提前致谢!

解决方法:

正如React docs所述

Often, several components need to reflect the same changing data. We
recommend lifting the shared state up to their closest common
ancestor.

There should be a single “source of truth” for any data that changes
in a React application. Usually, the state is first added to the
component that needs it for rendering. Then, if other components also
need it, you can lift it up to their closest common ancestor. Instead
of trying to sync the state between different components, you should
rely on the top-down data flow.

Lifting state involves writing more “boilerplate” code than two-way
binding approaches, but as a benefit, it takes less work to find and
isolate bugs. Since any state “lives” in some component and that
component alone can change it, the surface area for bugs is greatly
reduced. Additionally, you can implement any custom logic to reject or
transform user input.

所以基本上你需要提升那些正在用尽兄弟姐妹组件的树状态.因此,您首先实现将selectedItems存储为RightContainer中的状态是完全合理的并且是一种好的方法,因为父级不需要知道并且此数据由RightContainer的两个子组件共享,现在这两个子组件共享有一个单一的事实来源.

根据你的问题:

As feasible alternative I thought of adding a _selected property to
each item in state.right.data in MainContainer and pass the select
callback three levels down to SelectableList, handling all the
possible actions in MainContainer

我不同意这是比第一个更好的方法,因为您MainContainer不需要知道selectedItems或处理任何更新. MainContainer没有对这些状态做任何事情,只是将其传递下去.

考虑优化性能,你自己谈论实现一个shouldComponentUpdate,但是你可以通过扩展React.PureComponent创建组件来避免这种情况,这实际上是通过对state和props进行浅层比较来实现shouldComponentUpdate.

根据文件:

If your React component’s render() function renders the same result
given the same props and state, you can use React.PureComponent for a
performance boost in some cases.

但是,如果多个深度嵌套的组件正在使用相同的数据,那么使用redux并将该数据存储在redux-state中是有意义的.通过这种方式,整个App可以全局访问,并且可以在不直接相关的组件之间共享.

例如,考虑以下情况

const App = () => {
    <Router>
         <Route path="/" component={Home}/>
         <Route path="/mypage" component={MyComp}/>
    </Router>
}

现在,如果Home和MyComp都想访问相同的数据.您可以通过渲染道具调用数据作为道具从App传递.但是,通过使用连接函数将这两个组件连接到Redux状态可以轻松完成

const mapStateToProps = (state) => {
   return {
      data: state.data
   }
}

export connect(mapStateToProps)(Home);

和MyComp类似.此外,它还可以轻松配置更新相关信息的操作

此外,它还特别容易为您的应用程序配置Redux,并且您可以在各个Reducer中存储与相同内容相关的数据.通过这种方式,您也可以将应用程序数据模块化

标签:create-react-app,javascript,reactjs
来源: https://codeday.me/bug/20190915/1806458.html