根据 Redux 状态更改组件的布局 [英] Changing the layout of a component depending on Redux state

查看:24
本文介绍了根据 Redux 状态更改组件的布局的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在 React 中开发课程安排应用程序,并将其用作学习 redux 的机会.我目前正在设计一个浏览菜单(作为 Browse 组件实现),它在加载时显示大学中的学校列表.当用户单击其中一所学校时,它会显示该学校内的科目列表.但是,我希望学校显示为网格(两列),并且我希望将科目显示为列表(一列).他们也可能需要将不同的 props 提供给 Browse 组件.

我该怎么做?目前,我有一个 Browse 组件和一个 BrowseReduxContainer 组件.BrowseReduxContainer 组件使用 react-redux 中的 connect()、mapStateToProps 和 mapDispatchToProps 来填充 Browse 的 props.当我只显示学校时,这很好用,但我不确定如何根据状态修改 Browse 的布局.我应该根据状态给 connect() 不同的组件吗?或者我应该在 Browse 组件中实现逻辑来检查道具并相应地显示网格/列表?或者完全是别的什么?

actions.js

导出函数 showSubjects(schoolId) {返回 {类型:'SHOW_SUBJECTS',学校编号};}

浏览.js

const initialState = {currentView: '学校',学校:[{id:'AAAA',名称:'aaaa'},{id:'BBBB',名称:'bbbb'}],主题:[{id:'CCC',名称:'ccc'},{id:'DDD',名称:'ddd'}]};功能浏览(状态 = 初始状态,动作){开关(动作.类型){案例SHOW_SUBJECTS":返回 {...状态,当前视图:'主题'};默认:返回状态;}}导出默认浏览;

浏览ReduxContainer.jsx

import { connect } from 'react-redux';从'../actions/actions'导入{showSubjects};从'../components/Browse.jsx'导入浏览;功能道具过滤器(状态){开关(状态.currentView){案例学校":返回 state.schools;案例主题":返回 state.subjects;默认:throw new Error(`No such view: ${state.currentView}`);}}const mapStateToProps = (状态) =>({学校:道具过滤器(状态)});const mapDispatchToProps = (dispatch) =>({showSubjects: (schoolId) =>{调度(showSubjects(schoolId));}});const BrowseReduxContainer = connect(mapStateToProps, mapDispatchToProps)(Browse);导出默认的 BrowseReduxContainer;

浏览.jsx

从'react'导入React;从'material-ui/RaisedButton'导入RaisedButton;const Browse = (props) =>(<div>{props.schools.map((学校) => (<RaisedButton key={school.id} label={school.name} onClick={props.showSubjects(school.id)}/>))}

);导出默认浏览;

其他相关文件,如有需要,可以在这里查看:https://github.com/Joonpark13/serif.nu/tree/feature/browse

更新:在这一点上,我最好的猜测是让不同的视图组件拥有自己合适的 props,可能称为 BrowseA 和 BrowseB,并根据状态连接合适的组件.我想将此逻辑包含在 BrowseReduxContainer 内的 mapDispatchToProps 中,但后来我意识到 mapDispatchToProps 函数不将状态作为参数.我喜欢任何建议!

解决方案

connect 子组件上的状态

在子组件上使用connect有以下优点:

  • 您的父组件无需为 connect 连接其子组件所需的所有 props 而烦恼,即使父组件本身没有使用该 prop.

  • 子组件变得更加可重用且易于维护.

  • 避免盲目地将道具从父母传给孩子.如果 Child 需要相当多的 props,人们不想显式只传递所需的 props,而是倾向于在父级内部这样做:<Child {...this.props}/>.

    使用connect,你就知道你的组件得到了什么.

  • 您不必在父级和子级中重复 propTypes 定义.


将业务逻辑与视图分开:

业务逻辑是:

  • 任何基于来自 API 或用户输入的数据的计算
  • 数据规范化和格式化
  • 以小增量或功能完成,以便它们易于扩展、组合和维护
  • 在多个视图中重用业务逻辑功能.

观看次数应该:

  • 从状态和/或业务逻辑函数中提取准备好的数据

  • 根据数据显示或隐藏界面

  • 简化 UI 组件,使其体积小、可重用且易于维护

  • 通过业务逻辑函数的connect获取道具.


什么是业务逻辑功能?

业务逻辑函数是输入数据和输出修改数据的小型可重用函数.如果它们很小,它们可以很容易地重复使用和修改.业务逻辑功能应该是纯粹的.由于业务逻辑功能经常重用,它们在记忆.在某些语言中,它们被称为getter选择器.

为了简化记忆,您可以使用 reselect 库.它非常简单,因为它只做两件事:记忆和可重用性.请查看官方 API,了解有关如何执行此操作的更多信息.

优点:

  • 业务逻辑采用易于调试、增强、维护和阅读的小功能
  • 业务逻辑函数被记忆,因此重复调用是高效的
  • 业务逻辑是分离的,因此可以在整个应用中重复使用
  • 应用速度更快,因为主要操作高度优化

I'm developing a course scheduling application in react, and I'm using it as a chance to learn redux. There's a browse menu (implemented as the Browse component) that I'm currently designing and it displays the list of schools in the university upon load. When a user clicks on one of the schools, it displays a list of subjects within that school. However, I would like the schools to be displayed as a grid (two columns), and I would like the subjects to be displayed as a list (one column). They also may presumably require different props to be fed to the Browse component.

How would I go about doing this? Currently, I have a Browse component and a BrowseReduxContainer component. The BrowseReduxContainer component uses connect(), mapStateToProps, and mapDispatchToProps from react-redux to populate the props of Browse. This works fine when I'm just displaying schools, but I'm not sure how to modify the layout of Browse depending upon the state. Should I be giving connect() different components depending on the state? Or should I implement logic within the Browse component to check the prop and display a grid/list accordingly? Or something else entirely?

actions.js

export function showSubjects(schoolId) {
  return {
    type: 'SHOW_SUBJECTS',
    schoolId
  };
}

browse.js

const initialState = {
    currentView: 'schools',
    schools: [{id: 'AAAA', name: 'aaaa'}, {id: 'BBBB', name: 'bbbb'}],
    subjects: [{id: 'CCC', name: 'ccc'}, {id: 'DDD', name: 'ddd'}]
};

function browse(state = initialState, action) {
  switch (action.type) {
    case 'SHOW_SUBJECTS':
      return {
        ...state,
        currentView: 'subjects'
      };
    default:
      return state;
  }
}

export default browse;

BrowseReduxContainer.jsx

import { connect } from 'react-redux';
import { showSubjects } from '../actions/actions';
import Browse from '../components/Browse.jsx';

function propsFilter(state) {
  switch (state.currentView) {
    case 'schools':
      return state.schools;
    case 'subjects':
      return state.subjects;
    default:
      throw new Error(`No such view: ${state.currentView}`);
  }
}

const mapStateToProps = (state) => ({
  schools: propsFilter(state)
});

const mapDispatchToProps = (dispatch) => ({
  showSubjects: (schoolId) => {
    dispatch(showSubjects(schoolId));
  }
});

const BrowseReduxContainer = connect(mapStateToProps, mapDispatchToProps)(Browse);

export default BrowseReduxContainer;

Browse.jsx

import React from 'react';
import RaisedButton from 'material-ui/RaisedButton';

const Browse = (props) => (
  <div>
    {props.schools.map((school) => (
      <RaisedButton key={school.id} label={school.name} onClick={props.showSubjects(school.id)} />
    ))}
  </div>
);

export default Browse;

Other relevant files, if necessary, can be viewed here: https://github.com/Joonpark13/serif.nu/tree/feature/browse

UPDATE: My best guess at this point was to have different view components with their own appropriate props, perhaps called BrowseA and BrowseB and connect the appropriate one according to the state. I want to include this logic in mapDispatchToProps within BrowseReduxContainer, but then I realized the mapDispatchToProps function does not take state as a parameter. I'd love any suggestions!

解决方案

connect state on your Child components

Using connect on child components has the following advantages:

  • Your parent component need not bother about connecting all the props required by its children even though the parent itself is not using the prop.

  • Child components become more reusable, and easily maintainable.

  • Avoids passing down props blindly from parent to children. If the Child requires a considerable number of props, people don't want to explicitly pass only the required props, instead they tend to do this inside the parent: <Child {...this.props} />.

    Use connect and you know what your Component is getting.

  • You don't have to repeat propTypes definitions in parent and children.


Separate business logic from views:

Business logic is:

  • Any calculation based on data that came from the API or user input
  • Data normalization and formatting
  • Done in small increments or functions so that they are easily extendable, composable, and maintainable
  • Reuse the business logic functions in multiple views.

Views should:

  • Pull prepared data from state and/or business logic functions

  • Show or hide UI based on data

  • Simplify UI components so that they are small, reusable, and easily maintainable

  • Get props through connect from a business logic function.


What is a business logic function?

Business logic functions are small reusable functions that input data and output modified data. If they are small, they can be easily reused and modified. Business logic functions should be pure. Because business logic functions are often reused, they work best when memoized. In some languages these are called getters or selectors.

To streamline memoization, you may use reselect library. It’s a very simple as it only does two things: memoization and reusability. Take a look at the official API for more information on how it does that.

Advantages:

  • Business logic is in small functions that are easy to debug, enhance, maintain, read
  • Business logic functions are memoized so repeated calls are performant
  • Business logic is separated so it’s reusable across the app
  • The application is faster because main operations are highly optimized

这篇关于根据 Redux 状态更改组件的布局的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆