天道酬勤,学无止境

React: Material-UI GridListTile looses style attributes when called from within component

I have a UI where I render a <GridList> with tiles that I define as custom components.

When I first wrote this, I was a bit confused about the nature of React hooks, how props are passed etc. So, I was calling it as a regular JS function:

const VideoTile = ({...props}) => {
    const { url, classes } = props;
    
    return (
        <GridListTile key={url} cols={1} className={classes.videoTile} >
            <video src={url} className={classes.videoPreview} />
            <GridListTileBar title={url} />
        </GridListTile>
    )
}
const VideoBrowser = ({...props}) => {
    const {vidUrls, classes} = props; //for the sake of brevity
    return (
        <GridList cellHeight='auto' cols={4} className={classes.videoGridList}>
          {videoUrls.map((url) => VideoTile({url, classes}))}
        </GridList>
    )
}

Notice that I was adding a key attribute to the tile within the function to appease React.

Reviewing the code with a better understanding of React, I changed it such that it can be called with JSX syntax, using hooks within the component etc and hopefully following better practice. However, I've discovered that something about the way Material-UI operates on React's virtual DOM means that it renders the two children here very differently:

(I've removed hooks for now and am focussing on rendering single components alongside each other so I can compare in devtools).

<GridList cellHeight='auto' cols={4} className={classes.videoGridList}>
  {VideoTile({url, classes})}
  <VideoTile url={url} classes={classes} />
</GridList>

The first version has some element style attributes { width: 25%; height: auto; padding: 2px; } added to the outer <li>. The latter version doesn't, presumably because the code that adds them doesn't understand that the top-level element of <VideoTile> is actually a <GridListTile>, and, as such, of interest. I suppose I'll just re-arrange the code so that the <GridListTile> appears outside the function, but I'd like to understand the problem better, how I might solve it differently, or whether there's a general principle that I should understand to avoid similar problems in future.

评论

By the time I finished entering the question, I'd realised how to fix my particular bug for now, allowing more use of hooks within my components etc:

const VideoTileInner = ({...props}) => {
    const { url } = props;
    const classes = useStyles();
    
    return (
        <>
            <video src={url} className={classes.videoPreview} />
            <GridListTileBar title={url} />
        </>
    )
}

const VideoBrowser = ({...props}) => {
    const {vidUrls} = props;
    const classes = useStyles();
    return (
        <GridList cellHeight='auto' cols={4} className={classes.videoGridList}>
        {videoUrls.map((url) => {
          return (
            <GridListTile key={url} cols={1} className={classes.videoTile}>
              <VideoTileInner url={url} />
            </GridListTile>
          )
        })}
        </GridList>
    )
}

As mentioned in the question, though, I'd like to understand the problem better, how I might solve it differently, or whether there's a general principle that I should understand to avoid similar problems in future.

Or, indeed, whether this could be considered a bug in Material-UI.

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • Adding component with material-table changes Material-UI AppBar style
    My app is using Material-UI and material-table. A global theme is applied in the "index.js" file using "ThemeProvider" with as a child and then has children: <Fragment> <CssBaseline /> <MenuAppBar /> <main className={classes.main}> <Route path="/" exact component={Home} /> <Route path="/login" component={Login}></Route> </main> </Fragment> The component then has the component with the material-table. When I add in the table component and view that page the AppBar looses some of it's styling, e.g. background color and alignment in the dropdown buttons for Pofile and Logout (https://material-ui
  • 如何在react-bootstrap中更改活动单选按钮的背景颜色?(How to change background color of active radio button in react-bootstrap?)
    问题 在 React 项目中,我使用单选按钮列出日历日期和日期。 我的目的是更改这些单选按钮的背景颜色并保留它。 单击屏幕时它不应消失。 以下是代码供参考: {newDate.map((data, i) => ( <ButtonGroup toggle style={{ width: "100%" }}> <GridListTile style={gridListStylePhoto}> <h5>{currday(data.getDay())}</h5> <ToggleButton key={i} type="radio" active="true" variant="light" name="radio" value={currday(data.getDay()) + " " + data.getDate()} checked={radioValue === data.getDate()} onChange={(e) => { handleChange(e); }} > <br /> {data.getDate()} </ToggleButton> </GridListTile> </ButtonGroup> ))} 以下是样式参考: input[type="checkbox"], input[type="radio"] { display: none; } .btn-light
  • Material-UI Select,单击输入时如何在选择上应用 :focus-within 样式?(Material-UI Select, how to apply :focus-within styling on the select when the input is clicked?)
    问题
  • React hooks with firestore data - 1.1k reads in 30 seconds (from 2 collections with 3 documents with 2 attributes)
    I'm trying to understand how the Cloud Firestore read quota works. I have read this post and the response to it. My console was open, but I cannot construe how a single collection with 3 documents, each having 2 attributes constitutes a "busy console". I'm struggling to make sense of the documentation. I have two collections in firestore. Each one has 3 documents. Each document has 2 attributes. I'm using those attributes to populate options in the Autocomplete select menu from Material UI. In localhost, I have been running the form to test getting those attributes into an Autocomplete select
  • 使用 React 在 Material UI 对话框中形成表单(Form in Material UI Dialog using React)
    问题 我试图让一个表单在 Material UI Dialog 组件内部工作。 如果我将 Dialog 包装在表单标签中,它们甚至不会出现在生成的 html 中(不知道为什么)...... <form onSubmit={someFunction}> <Dialog> ... </Dialog> </form> 如果我反转它并将表单标签放在对话框中,表单元素会显示在生成的 html 中,但是设置为 type="submit" 的操作按钮不会触发表单的 onSubmit。 <Dialog> <form onSubmit={someFunction}> ... </form> </Dialog> 有没有人成功地让这种组合发挥作用? 我知道我可以直接从操作按钮单击调用该函数,但我也在使用 Redux Form 并且在应用程序中有其他非对话框表单,所以我将它绑定到表单元素。 所以我真的需要以某种方式从对话框调用表单提交。 回答1 实际上 - 我有/有onSubmit={handleSubmit(this.myFunction)}开始,这不是问题。 问题原来是 Material UI 如何安装Dialog (这显然与react-toolbox不同)。 他们将它安装在身体上——我假设是为了更容易定位——所以Dialog之外的任何东西都被忽略了。 对于 Dialog 内的表单,按钮位于表单之外
  • JSS 中的 MUI 全局类名称有多可靠?(How reliable are MUI Global Class names in JSS?)
    问题 我有这样的代码: const formControlStyles = { root: { '&:hover .MuiFormLabel-root': { } } } 在主题覆盖中使用类名来访问其他组件是否安全? 此外,是否有一种 JSS 方式可以从其他组件中嵌套样式? 回答1 v5 的更新这个答案最初是关于 Material-UI 的 v4 编写的。 在 v5 中,Material-UI 不再使用全局类名来应用默认样式——用于默认样式的类具有由 Emotion 生成的类名。 全局类名仍然适用,但它们不再受嵌套主题的影响,因此在 v5 中利用全局类名进行覆盖是完全安全的,而无需使用[class*=...下面回答。 使用全局类名是相当安全的,但有一个警告(在 v4 中)。 如果您利用嵌套主题,嵌套主题中应用的全局类名称将具有不可预测的后缀(例如MuiFormLabel-root-371 )。 此后缀是必要的,因为与嵌套主题关联的默认样式可能不同。 为了以完全安全的方式定位类名,您可以使用*=属性选择器(例如[class*="MuiFormLabel-root"] ),它检查元素是否具有包含MuiFormLabel-root的类名而不是需要完全匹配。 您可以在此处查看 Material-UI 本身中使用的这种方法。 只要您不打算使用嵌套主题
  • How to change background color of active radio button in react-bootstrap?
    In a React project I've radio buttons enlisting calendar dates and days. My intention is to change the background color of those radio buttons and also persist it. It should not fade away when clicked on screen. The following is the code for reference: {newDate.map((data, i) => ( <ButtonGroup toggle style={{ width: "100%" }}> <GridListTile style={gridListStylePhoto}> <h5>{currday(data.getDay())}</h5> <ToggleButton key={i} type="radio" active="true" variant="light" name="radio" value={currday(data.getDay()) + " " + data.getDate()} checked={radioValue === data.getDate()} onChange={(e) => {
  • 无效的钩子调用。 使用 material-ui 将样式应用于类基组件时,只能在函数组件的主体内部调用钩子(Invalid hook call. Hooks can only be called inside of the body of a function component when apply style to class base component with material-ui)
    问题 我刚刚开始使用 material-ui 学习 reactjs,但是在将样式应用于我的组件时出现此错误。 我的代码: const useStyles = makeStyles(theme => ({ root: { flexGrow: 1, }, menuButton: { marginRight: theme.spacing(2), }, title: { flexGrow: 1, }, })); class NavMenu extends React.Component { constructor(props) { super(props); this.state = { isOpen: false }; } render() { const classes = useStyles(); return ( <div className={classes.root}> <AppBar position="static"> <Toolbar> <IconButton edge="start" className={classes.menuButton} color="inherit" aria-label="Menu" > <MenuIcon /> </IconButton> <Typography variant="h6" className={classes.title}
  • 调用动作时无限后循环(infinite post loop when calling action)
    问题
  • 如何屏蔽我的 Material-UI TextField?(How Can I Mask My Material-UI TextField?)
    问题 我有一个简短的电话号码文本字段。 然后我想屏蔽这个表单字段,比如 (0)xxx xxx xx xx。 我正在尝试将 react-input-mask 插件与 Material-UI 一起使用。 但是如果我想更改输入值,这不会更新我的主要 TextField。 <TextField ref="phone" name="phone" type="text" value={this.state.phone} onChange={this.onChange} > <InputMask value={this.state.phone} onChange={this.onChange} mask="(0)999 999 99 99" maskChar=" " /> </TextField> 实际上,我找不到任何使用 Material-UI 进行遮罩的文档。 我想弄清楚如何与其他插件一起使用。 回答1 更新 版本:material-ui 0.20.2,react-input-mask 2.0.4 似乎 API 发生了一些变化: <InputMask mask="(0)999 999 99 99" value={this.state.phone} disabled={false} maskChar=" " > {() => <TextField />} </InputMask> 演示 原来的
  • React testing library: Test attribute / prop
    I'm writing a React app using TypeScript. I use material-ui for my components and react-testing-library for my unit tests. I'm writing a wrapper for material-ui's Grid component so that I always have an item. import Grid from "@material-ui/core/Grid"; import withStyles, { WithStyles } from "@material-ui/core/styles/withStyles"; import React, { PureComponent } from "react"; import styles from "./styles"; export interface OwnProps { className?: string; } export interface Props extends WithStyles<typeof styles>, OwnProps {} export interface DefaultProps { className: string; } export class
  • Material-UI 的 Tabs 与 react router 4 集成?(Material-UI's Tabs integration with react router 4?)
    问题 新的 react-router 语法使用Link组件来移动路由。 但是这怎么能与material-ui集成呢? 就我而言,我使用标签作为主要导航系统,所以理论上我应该有这样的东西: const TabLink = ({ onClick, href, isActive, label }) => <Tab label={label} onActive={onClick} /> export default class NavBar extends React.Component { render () { return ( <Tabs> <Link to="/">{params => <TabLink label="Home" {...params}/>}</Link> <Link to="/shop">{params => <TabLink label="shop" {...params}/>}</Link> <Link to="/gallery">{params => <TabLink label="gallery" {...params}/>}</Link> </Tabs> ) } } 但是在渲染的时候,material-ui 会抛出一个错误,说Tabs的 child 必须是一个Tab组件。 继续前进的方法是什么? 如何管理选项卡的isActive道具? 提前致谢 回答1
  • Material UI - 在 AppBar 单击打开 LeftNav / Drawer(Material UI - Open LeftNav / Drawer on AppBar click)
    问题 我正在发现 ReactJS 和 material-ui (http://material-ui.com/)。 我尝试为我的应用程序创建一个默认模板。 我想在分离的组件中使用 AppBar 和LeftNav(在新版本中在 Drawer 中重命名) 。 默认情况下,AppBar 上有一个菜单按钮。 我想用它来打开 LeftNav 但我不知道如何调用我的 LeftBarComponent 组件函数来打开它。 我几乎已经了解如何在组件之间进行通信,但就我而言,我不知道该怎么做,因为没有关于它的文档。 我知道打开 LeftNav 元素的唯一方法是使用 LeftNav.toggle() http://material-ui.com/#/components/left-nav 谢谢你的帮助。 默认.jsx use strict'; var React = require('react'); var pageStore = require('../../stores/page'); var MainNavbar = require('../modules/navbar.jsx'); var LeftNavbar = require('../modules/leftbar.jsx'); var getState = function() { return { title: pageStore
  • 如何设置类似于 Material-UI 的轮廓文本字段的静态轮廓 div?(How can I set an static outlined div similar to Material-UI's outlined textfield?)
    问题 我想将一些 TextFields 包装在一个概述的容器中,我找到了这个答案。 这项工作是我想要的: 但是,当我单击内部文本字段时,所有文本字段都聚焦: 这是我的代码: import React from "react"; import ReactDOM from "react-dom"; import OutlinedDiv from "./OutlinedDiv"; import TextField from "@material-ui/core/TextField"; import Grid from "@material-ui/core/Grid"; function App() { return ( <div className="App"> <OutlinedDiv label="DIV"> <Grid container justify="center" alignItems="center" spacing={3}> <Grid item sm={4} xs={12}> <TextField label="Text1" variant="outlined" /> </Grid> <Grid item sm={4} xs={12}> <TextField label="Text2" variant="outlined" /> </Grid> <Grid item
  • Material-UI 线性进度条不起作用(Material-UI LinearProgress bar not working)
    问题 我有一个简单的文件上传实用程序,为此我使用了 react-dropzone,同时我想使用 material-ui LinearProgress 条来显示进度。 下面显示的是我创建的组件,它呈现文件上传实用程序和 LinearProgress 栏。 我正在使用 superagent 库使用 multipart formdata 将后端实际上传到后端。 超级代理的请求允许上传进度的回调或事件处理程序。 在我的代码中,progress 事件处理程序被成功调用并由 console.log 语句证明。 在每次进度调用时,我都会更新 LinearProgress 栏使用的this.state.completed属性。 问题是进度条没有前进。 我肯定错过了一些非常简单的东西。 非常感谢您的任何帮助,并提前感谢您。 import React, {Component} from 'react'; import Dropzone from 'react-dropzone'; import request from 'superagent'; import LinearProgress from 'material-ui/LinearProgress'; import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'
  • Material-UI LinearProgress bar not working
    I have a simple file upload utility, for which I am using react-dropzone, and in conjunction to that I wanted to use material-ui LinearProgress bar to show the progress. Shown below is the component I created which renders the file upload utility along with the LinearProgress bar. I am using superagent library for the actual upload of the back to the backend using multipart formdata. The superagent's request allows a callback or an event handler for upload progress. In my code, the progress event handler gets successfully called and is proved by the console.log statements. On each progress
  • 嵌套列表中的 RadioButtonGroup(RadioButtonGroup within nested List)
    问题 我正在使用 Material-UI,我想使用 List/ListItem 组件对我的单选按钮进行分组。 类似于这个: <RadioButtonGroup ...> <List> <ListItem ... nestedItems={[ <RadioButton ... />, <RadioButton ... /> ]} /> <ListItem ... nestedItems={[ <RadioButton ... />, <RadioButton ... /> ]} /> </List> </RadioButtonGroup> 有没有办法存档这个? 谢谢。 回答1 我的临时解决方法是使用外观和行为类似于单选按钮的复选框。 import List from 'material-ui/lib/lists/list'; import ListItem from 'material-ui/lib/lists/list-item'; import Checkbox from 'material-ui/lib/checkbox'; import RadioChecked from 'material-ui/lib/svg-icons/toggle/radio-button-checked'; import RadioUnchecked from 'material-ui/lib
  • 生产/构建中的 Material-UI 渲染错误(Material-UI Rendering Bugs in production / build)
    问题 我在构建我的 react-app 时遇到了大问题。 我在正常的 react-scripts start dev-server 上使用 material-ui/core v.4.10.2 一切正常。 但是当通过 Nginx 或 npm-module serve 构建和提供服务时,渲染无法正常工作...... (我在material-ui Github上看到过类似的问题,但是都被(假地)关闭了 这是我的 package.json 以防我的依赖项出现问题(我当然不认为是这种情况) { "name": "web_app", "version": "0.0.1", "private": true, "dependencies": { "@material-ui/core": "^4.10.2", "@material-ui/styles": "4.10.0", "@material-ui/icons": "^4.2.1", "@material-ui/lab": "^4.0.0-alpha.45", "rc-color-picker": "^1.2.6", "react": "^16.9.0", "react-dom": "^16.9.0", "react-infinite-scroll-hook": "^2.0.1", "react-router-dom": "^5.0.1",
  • 如何使用 MenuItem 进行导航? 材料-ui V1(how navigate using the MenuItem? material-ui V1)
    问题
  • 如何覆盖(覆盖)material-ui(React)中的类和样式(How to override (overwrite) classes and styles in material-ui (React))
    问题