从 material-ui 的 GridList 中提取属性
Extracting properties from material-ui's GridList
几天前我才开始学习React,所以如果这个问题听起来很愚蠢,请原谅我。
在这项工作任务中,我必须使用 material-ui 的 GridList 实现一个 'Like' 系统。总共会有八张图片,用户可以通过点击喜欢按钮来喜欢它们。在我当前的代码中,用户可以单击“赞”按钮,但所有“赞”按钮都会受到影响,而不仅仅是一个。而且,点赞数并没有增加。
所以我的问题是,当用户单击 'Like' 按钮时,如何更改点赞数并确保只有 1 个按钮受到影响?我已经尝试过 props 甚至 lodash,但我似乎无法找出问题所在。下面是我的 GridList 部分的全部代码。任何帮助将不胜感激。
import _ from 'lodash';
import React from 'react';
import {GridList, GridTile} from 'material-ui/GridList';
import Subheader from 'material-ui/Subheader';
import baseTheme from 'material-ui/styles/baseThemes/lightBaseTheme';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
//GridList style
const styles = {
root: {
display: 'flex',
flexWrap: 'wrap',
justifyContent: 'space-around',
},
gridList: {
width: 1000,
height: 500,
},
};
//data for the GridList
var tilesData = [
{
img: './images/image_01.jpg',
title: 'Breakfast',
likes: 0,
},
{
img: './images/image_02.jpg',
title: 'Tasty burger',
likes: 0,
},
{
img: './images/image_03.jpg',
title: 'Camera',
likes: 0,
},
{
img: './images/image_04.jpg',
title: 'Morning',
likes: 0,
},
{
img: './images/image_05.jpg',
title: 'Hats',
likes: 0,
},
{
img: './images/image_06.jpg',
title: 'Honey',
likes: 0,
},
{
img: './images/image_07.jpg',
title: 'Vegetables',
likes: 0,
},
{
img: './images/image_08.jpg',
title: 'Water plant',
likes: 0,
},
];
export default class Grid extends React.Component {
constructor(props){
super(props);
this.state = {
like: false,
likes: tilesData.likes,
};
this.post = this.post.bind(this);
this.delete = this.delete.bind(this);
}
//if Like button is clicked
post(){
this.setState({ like: true});
let likes = this.state.likes;
likes++;
this.setState({likes: likes});
//this.tilesData.likes = likes;
}
//if Like button is "unclicked"
delete(){
this.setState({ like: false});
let likes = this.state.likes;
likes--;
this.setState({likes: likes});
//this.tilesData.likes = likes;
}
getChildContext() {
return { muiTheme: getMuiTheme(baseTheme) };
}
render(){
const likeBtn = this.state.like ? <img src="./images/icons/icon_2.png" onClick={this.delete} /> : <img src="./images/icons/icon_1.png" onClick={this.post} />;
return (
<div style={styles.root}>
<GridList
cellHeight={200}
cols={4}
style={styles.gridList}
>
<Subheader>December</Subheader>
{tilesData.map((tile) => (
<GridTile
key={tile.img}
title={tile.title}
subtitle={<span>Likes: <b>{tile.likes}</b></span>}
actionIcon={likeBtn}
>
<img src={tile.img} />
</GridTile>
))}
</GridList>
</div>
);
}
}
Grid.childContextTypes = {
muiTheme: React.PropTypes.object.isRequired,
}
问题
'State' of like 按钮在循环外定义意味着相同的 'state' 与所有 GridTile 共享组件(对于所有图像)。
当您单击 'like' 按钮时,您正在更改 Grid 父组件中 'like' 按钮的 'state' 和相同'state' 用于所有 喜欢 按钮。
这就是它影响所有赞按钮的原因。
解决方案
'state' 应该为每个 like 按钮单独定义。另外 delete 和 post 方法应该在 GridTile 中的循环方式中定义。
但 GridTile 是 material-ui 库的一部分,因此不要更改此库,而是在 GridTile 组件上创建一个包装器。
网格组件将调用组件让我们说它是循环内的 GridTileCustom 组件。
在 GridTileCustom 组件中,您需要定义 delete 和 post 方法,您在 'onClick' 中使用事件
所以你的最终代码看起来像
import React from 'react';
import {GridList, GridTile} from 'material-ui/GridList';
import Subheader from 'material-ui/Subheader';
import baseTheme from 'material-ui/styles/baseThemes/lightBaseTheme';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import IconButton from 'material-ui/IconButton';
const thumbsIcon = "glyphicon glyphicon-thumbs-up";
const styles = {
root: {
display: 'flex',
flexWrap: 'wrap',
justifyContent: 'space-around',
},
gridList: {
width: 1000,
height: 500,
},
};
var tilesData = [
{
img: './images/image_01.jpg',
title: 'Breakfast',
likes: 0,
icon: './images/icons/icon_1.png',
},
{
img: './images/image_02.jpg',
title: 'Tasty burger',
likes: 0,
icon: './images/icons/icon_1.png',
},
{
img: './images/image_03.jpg',
title: 'Camera',
likes: 0,
icon: './images/icons/icon_1.png',
},
{
img: './images/image_04.jpg',
title: 'Morning',
likes: 0,
icon: './images/icons/icon_1.png',
},
{
img: './images/image_05.jpg',
title: 'Hats',
likes: 0,
icon: './images/icons/icon_1.png',
},
{
img: './images/image_06.jpg',
title: 'Honey',
likes: 0,
icon: './images/icons/icon_1.png',
},
{
img: './images/image_07.jpg',
title: 'Vegetables',
likes: 0,
icon: './images/icons/icon_1.png',
},
{
img: './images/image_08.jpg',
title: 'Water plant',
likes: 0,
icon: './images/icons/icon_1.png',
},
];
export default class Grid extends React.Component {
constructor(props){
super(props);
this.state = {
like: false,
likes: tilesData.likes,
};
// this.post = this.post.bind(this);
// this.delete = this.delete.bind(this);
}
// post(){
// this.setState({ like: true});
// let likes = this.state.likes;
// likes++;
// this.setState({likes: likes});
// //this.tilesData.likes = likes;
// }
// delete(){
// this.setState({ like: false});
// let likes = this.state.likes;
// likes--;
// this.setState({likes: likes});
// //this.tilesData.likes = likes;
// }
getChildContext() {
return { muiTheme: getMuiTheme(baseTheme) };
}
render(){
return (
<div style={styles.root}>
<GridList
cellHeight={200}
cols={4}
style={styles.gridList}
>
<Subheader>December</Subheader>
{tilesData.map((tile) => (
<GridTileInternal
key={tile.img}
img={tile.img}
title={tile.title}
subtitle={tile.likes}
// actionIcon={likeBtn}
>
</GridTileInternal>
))}
</GridList>
</div>
);
}
}
class GridTileInternal extends React.Component {
constructor(props){
super(props);
this.state = {
like: false,
likes: tilesData.likes,
};
this.post = this.post.bind(this);
this.delete = this.delete.bind(this);
}
post(){
this.setState({ like: true});
let likes = this.state.likes;
likes++;
this.setState({likes: likes});
//this.tilesData.likes = likes;
}
delete(){
this.setState({ like: false});
let likes = this.state.likes;
likes--;
this.setState({likes: likes});
//this.tilesData.likes = likes;
}
render(){
const likeBtn = this.state.like ? <img src="./images/icons/icon_2.png" onClick={this.delete} /> : <img src="./images/icons/icon_1.png" onClick={this.post} />;
return (
<GridTile
key={this.props.img}
title={this.props.title}
subtitle={<span>Likes: <b>{this.props.subtitle}</b></span>}
actionIcon={likeBtn}
>
<img src={this.props.img} />
</GridTile>
);
}
}
Grid.childContextTypes = {
muiTheme: React.PropTypes.object.isRequired,
}
几天前我才开始学习React,所以如果这个问题听起来很愚蠢,请原谅我。
在这项工作任务中,我必须使用 material-ui 的 GridList 实现一个 'Like' 系统。总共会有八张图片,用户可以通过点击喜欢按钮来喜欢它们。在我当前的代码中,用户可以单击“赞”按钮,但所有“赞”按钮都会受到影响,而不仅仅是一个。而且,点赞数并没有增加。
所以我的问题是,当用户单击 'Like' 按钮时,如何更改点赞数并确保只有 1 个按钮受到影响?我已经尝试过 props 甚至 lodash,但我似乎无法找出问题所在。下面是我的 GridList 部分的全部代码。任何帮助将不胜感激。
import _ from 'lodash';
import React from 'react';
import {GridList, GridTile} from 'material-ui/GridList';
import Subheader from 'material-ui/Subheader';
import baseTheme from 'material-ui/styles/baseThemes/lightBaseTheme';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
//GridList style
const styles = {
root: {
display: 'flex',
flexWrap: 'wrap',
justifyContent: 'space-around',
},
gridList: {
width: 1000,
height: 500,
},
};
//data for the GridList
var tilesData = [
{
img: './images/image_01.jpg',
title: 'Breakfast',
likes: 0,
},
{
img: './images/image_02.jpg',
title: 'Tasty burger',
likes: 0,
},
{
img: './images/image_03.jpg',
title: 'Camera',
likes: 0,
},
{
img: './images/image_04.jpg',
title: 'Morning',
likes: 0,
},
{
img: './images/image_05.jpg',
title: 'Hats',
likes: 0,
},
{
img: './images/image_06.jpg',
title: 'Honey',
likes: 0,
},
{
img: './images/image_07.jpg',
title: 'Vegetables',
likes: 0,
},
{
img: './images/image_08.jpg',
title: 'Water plant',
likes: 0,
},
];
export default class Grid extends React.Component {
constructor(props){
super(props);
this.state = {
like: false,
likes: tilesData.likes,
};
this.post = this.post.bind(this);
this.delete = this.delete.bind(this);
}
//if Like button is clicked
post(){
this.setState({ like: true});
let likes = this.state.likes;
likes++;
this.setState({likes: likes});
//this.tilesData.likes = likes;
}
//if Like button is "unclicked"
delete(){
this.setState({ like: false});
let likes = this.state.likes;
likes--;
this.setState({likes: likes});
//this.tilesData.likes = likes;
}
getChildContext() {
return { muiTheme: getMuiTheme(baseTheme) };
}
render(){
const likeBtn = this.state.like ? <img src="./images/icons/icon_2.png" onClick={this.delete} /> : <img src="./images/icons/icon_1.png" onClick={this.post} />;
return (
<div style={styles.root}>
<GridList
cellHeight={200}
cols={4}
style={styles.gridList}
>
<Subheader>December</Subheader>
{tilesData.map((tile) => (
<GridTile
key={tile.img}
title={tile.title}
subtitle={<span>Likes: <b>{tile.likes}</b></span>}
actionIcon={likeBtn}
>
<img src={tile.img} />
</GridTile>
))}
</GridList>
</div>
);
}
}
Grid.childContextTypes = {
muiTheme: React.PropTypes.object.isRequired,
}
问题
'State' of like 按钮在循环外定义意味着相同的 'state' 与所有 GridTile 共享组件(对于所有图像)。
当您单击 'like' 按钮时,您正在更改 Grid 父组件中 'like' 按钮的 'state' 和相同'state' 用于所有 喜欢 按钮。
这就是它影响所有赞按钮的原因。
解决方案
'state' 应该为每个 like 按钮单独定义。另外 delete 和 post 方法应该在 GridTile 中的循环方式中定义。
但 GridTile 是 material-ui 库的一部分,因此不要更改此库,而是在 GridTile 组件上创建一个包装器。 网格组件将调用组件让我们说它是循环内的 GridTileCustom 组件。
在 GridTileCustom 组件中,您需要定义 delete 和 post 方法,您在 'onClick' 中使用事件 所以你的最终代码看起来像
import React from 'react';
import {GridList, GridTile} from 'material-ui/GridList';
import Subheader from 'material-ui/Subheader';
import baseTheme from 'material-ui/styles/baseThemes/lightBaseTheme';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import IconButton from 'material-ui/IconButton';
const thumbsIcon = "glyphicon glyphicon-thumbs-up";
const styles = {
root: {
display: 'flex',
flexWrap: 'wrap',
justifyContent: 'space-around',
},
gridList: {
width: 1000,
height: 500,
},
};
var tilesData = [
{
img: './images/image_01.jpg',
title: 'Breakfast',
likes: 0,
icon: './images/icons/icon_1.png',
},
{
img: './images/image_02.jpg',
title: 'Tasty burger',
likes: 0,
icon: './images/icons/icon_1.png',
},
{
img: './images/image_03.jpg',
title: 'Camera',
likes: 0,
icon: './images/icons/icon_1.png',
},
{
img: './images/image_04.jpg',
title: 'Morning',
likes: 0,
icon: './images/icons/icon_1.png',
},
{
img: './images/image_05.jpg',
title: 'Hats',
likes: 0,
icon: './images/icons/icon_1.png',
},
{
img: './images/image_06.jpg',
title: 'Honey',
likes: 0,
icon: './images/icons/icon_1.png',
},
{
img: './images/image_07.jpg',
title: 'Vegetables',
likes: 0,
icon: './images/icons/icon_1.png',
},
{
img: './images/image_08.jpg',
title: 'Water plant',
likes: 0,
icon: './images/icons/icon_1.png',
},
];
export default class Grid extends React.Component {
constructor(props){
super(props);
this.state = {
like: false,
likes: tilesData.likes,
};
// this.post = this.post.bind(this);
// this.delete = this.delete.bind(this);
}
// post(){
// this.setState({ like: true});
// let likes = this.state.likes;
// likes++;
// this.setState({likes: likes});
// //this.tilesData.likes = likes;
// }
// delete(){
// this.setState({ like: false});
// let likes = this.state.likes;
// likes--;
// this.setState({likes: likes});
// //this.tilesData.likes = likes;
// }
getChildContext() {
return { muiTheme: getMuiTheme(baseTheme) };
}
render(){
return (
<div style={styles.root}>
<GridList
cellHeight={200}
cols={4}
style={styles.gridList}
>
<Subheader>December</Subheader>
{tilesData.map((tile) => (
<GridTileInternal
key={tile.img}
img={tile.img}
title={tile.title}
subtitle={tile.likes}
// actionIcon={likeBtn}
>
</GridTileInternal>
))}
</GridList>
</div>
);
}
}
class GridTileInternal extends React.Component {
constructor(props){
super(props);
this.state = {
like: false,
likes: tilesData.likes,
};
this.post = this.post.bind(this);
this.delete = this.delete.bind(this);
}
post(){
this.setState({ like: true});
let likes = this.state.likes;
likes++;
this.setState({likes: likes});
//this.tilesData.likes = likes;
}
delete(){
this.setState({ like: false});
let likes = this.state.likes;
likes--;
this.setState({likes: likes});
//this.tilesData.likes = likes;
}
render(){
const likeBtn = this.state.like ? <img src="./images/icons/icon_2.png" onClick={this.delete} /> : <img src="./images/icons/icon_1.png" onClick={this.post} />;
return (
<GridTile
key={this.props.img}
title={this.props.title}
subtitle={<span>Likes: <b>{this.props.subtitle}</b></span>}
actionIcon={likeBtn}
>
<img src={this.props.img} />
</GridTile>
);
}
}
Grid.childContextTypes = {
muiTheme: React.PropTypes.object.isRequired,
}