栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

在React中无限渲染

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

在React中无限渲染

就像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:沉浸式(作者或暴民制造)。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/649786.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号