就像izb提到的那样,pb的根本原因是在纯组件上进行的业务调用,而该组件只是被加载了。这是因为您的组件做出了业务决策(<=>“我决定何时必须在自己体内显示某些内容”)。在React中这不是一个好习惯,甚至在使用redux时也不是。该组件必须尽可能地愚蠢,甚至不能决定做什么和何时进行。
正如我在您的项目中看到的那样,您没有正确处理组件和容器的概念。您的容器中不应包含任何逻辑,因为它应该只是愚蠢的纯组件的包装。像这样:
import { connect, Dispatch } from "react-redux";import { push, RouterAction, RouterState } from "react-router-redux";import ApplicationBarComponent from "../components/ApplicationBar";export function mapStateToProps({ routing }: { routing: RouterState }) { return routing;}export function mapDispatchToProps(dispatch: Dispatch<RouterAction>) { return { navigate: (payload: string) => dispatch(push(payload)), };}const tmp = connect(mapStateToProps, mapDispatchToProps);export default tmp(ApplicationBarComponent);和匹配的组件:
import AppBar from '@material-ui/core/AppBar';import IconButton from '@material-ui/core/IconButton';import Menu from '@material-ui/core/Menu';import MenuItem from '@material-ui/core/MenuItem';import { StyleRules, Theme, withStyles, WithStyles } from '@material-ui/core/styles';import Tab from '@material-ui/core/Tab';import Tabs from '@material-ui/core/Tabs';import Toolbar from '@material-ui/core/Toolbar';import Typography from '@material-ui/core/Typography';import AccountCircle from '@material-ui/icons/AccountCircle';import MenuIcon from '@material-ui/icons/Menu';import autobind from "autobind-decorator";import * as React from "react";import { push, RouterState } from "react-router-redux";const styles = (theme: Theme): StyleRules => ({ flex: { flex: 1 }, menuButton: { marginLeft: -12, marginRight: 20, }, root: { backgroundColor: theme.palette.background.paper, flexGrow: 1 },});export interface IProps extends RouterState, WithStyles { navigate: typeof push;}@autobindclass ApplicationBar extends React.PureComponent<IProps, { anchorEl: HTMLInputElement | undefined }> { constructor(props: any) { super(props); this.state = { anchorEl: undefined }; } public render() { const auth = true; const { classes } = this.props; const menuOpened = !!this.state.anchorEl; return ( <div className={classes.root}> <AppBar position="fixed" color="primary"> <Toolbar> <IconButton className={classes.menuButton} color="inherit" aria-label="Menu"> <MenuIcon /> </IconButton> <Typography variant="title" color="inherit" className={classes.flex}> Title </Typography> <Tabs value={this.getPathName()} onChange={this.handleNavigate} > {} <Tab label="Counter 1" value="/counter1" /> <Tab label="Counter 2" value="/counter2" /> <Tab label="Register" value="/register" /> <Tab label="Forecast" value="/forecast" /> </Tabs> {auth && ( <div> <IconButton aria-owns={menuOpened ? 'menu-appbar' : undefined} aria-haspopup="true" onClick={this.handleMenu} color="inherit" > <AccountCircle /> </IconButton> <Menu id="menu-appbar" anchorEl={this.state.anchorEl} anchorOrigin={{ horizontal: 'right', vertical: 'top', }} transformOrigin={{ horizontal: 'right', vertical: 'top', }} open={menuOpened} onClose={this.handleClose} > <MenuItem onClick={this.handleClose}>Profile</MenuItem> <MenuItem onClick={this.handleClose}>My account</MenuItem> </Menu> </div> )} </Toolbar> </AppBar> </div > ); } private getPathName(): string { if (!this.props.location) { return "/counter1"; } return (this.props.location as { pathname: string }).pathname; } private handleNavigate(event: React.ChangeEvent<{}>, value: any) { this.props.navigate(value as string); } private handleMenu(event: React.MouseEvent<HTMLInputElement>) { this.setState({ anchorEl: event.currentTarget }); } private handleClose() { this.setState({ anchorEl: undefined }); }}export default withStyles(styles)(ApplicationBar);然后,您会告诉我:“但是,我在哪里发起可以填满列表的呼叫?” 好吧,我在这里看到您使用redux-
thunk(我更喜欢redux可观察的…学习起来更复杂,但是waaaaaaaaaaaaaaaaaaay更强大),然后应该将其重做,从而启动此调度!
总结一下:
- 组件:最愚蠢的元素,通常只应具有render方法,以及一些其他使用户事件冒泡的方法处理程序。此方法仅负责向用户显示其属性。除非您拥有仅属于此组件的视觉信息(例如,弹出窗口的可见性),否则不要使用状态。显示或更新的所有内容均来自上方:更高级别的组件或容器。它没有决定更新自己的值。充其量,它会处理子组件上的用户事件,然后在上面的另一个事件中冒泡,然后……也许在某些时候,其容器会返回一些新属性!
- 容器:非常愚蠢的逻辑,它包含将顶级组件包装到redux中,以便将事件插入到动作中,并将存储的某些部分插入到属性中
- Redux thunk(或可观察到的redux):它处理整个用户应用程序逻辑。这个家伙是唯一知道何时触发什么的人。如果前端的一部分必须包含复杂性,那就是这个!
- 精简器:定义如何组织存储中的数据以使其尽可能易于使用。
- 存储:理想情况下,每个顶层容器一个,唯一一个包含必须向用户显示数据的容器。没人应该。
如果遵循这些原则,您将永远不会面临任何问题,例如“为什么要两次被打扰?以及……是谁打出来的?为什么在这一刻呢?”
其他:如果您使用redux,请使用不变性框架。否则,您可能会遇到问题,因为reducer必须是纯函数。为此,您可以使用一种流行的immutable.js,但一点都不方便。而后来的驱逐剂实际上是一个杀手er:沉浸式(作者或暴民制造)。



