使用 Isotope.js 和 React 来创建带过滤器的砌体布局?
Using Isotope.js with React to create a masonry layout with filters?
我正在使用 Gatsby 构建一个博客,我正在尝试实现一个带有过滤器的砖石网格来显示我的帖子。过去,我是通过使用 Isotope.js 来做到这一点的,所以我又使用了它。但是,它并没有真正起作用。我对 React 还是很陌生,所以我不知道哪里出了问题。
我收到此错误:TypeError: Cannot read property 'map' of undefined
import React from 'react';
import Img from 'gatsby-image';
import { Link, StaticQuery } from 'gatsby';
import Isotope from "isotope-layout/js/isotope";
import PropTypes from 'prop-types';
class FilterGrid extends React.Component {
constructor(props) {
super(props);
this.onFilterChange = this.onFilterChange.bind(this);
}
// Click Function
onFilterChange = (newFilter) => {
if (this.iso === undefined) {
this.iso = new Isotope('#grid-container', {
itemSelector: '.grid-item',
layoutMode: "fitRows",
percentPosition: true,
fitRows: {
gutter: '.gutter-sizer'
}
});
}
if(newFilter === '*') {
this.iso.arrange({ filter: `*` });
} else {
this.iso.arrange({ filter: `.${newFilter}` });
}
}
render() {
const posts = this.props.data.allMarkdownRemark.node
return(
// Filter Buttons
<section className="section">
<div className="button-group filter-button-group grid-filters">
<div className="tabs is-centered is-toggle">
<ul id="portfolio-flters">
<li data-filter="*" onClick={() => {this.onFilterChange("*")}}>All</li>
<li data-filter="brandy" onClick={() => {this.onFilterChange("brandy")}}>Brandy</li>
<li data-filter="cachaça" onClick={() => {this.onFilterChange("cachaça")}}>Cachaça</li>
<li data-filter="gin" onClick={() => {this.onFilterChange("gin")}}>Gin</li>
<li data-filter="mexcal" onClick={() => {this.onFilterChange("mezcal")}}>Mezcal</li>
<li data-filter="rum" onClick={() => {this.onFilterChange("rum")}}>Rum</li>
<li data-filter="tequila" onClick={() => {this.onFilterChange("tequila")}}>Tequila</li>
<li data-filter="whiskey" onClick={() => {this.onFilterChange("whiskey")}}>Whiskey</li>
<li data-filter="vodka" onClick={() => {this.onFilterChange("vodka")}}>Vodka</li>
</ul>
</div>
</div>
<div className="grid" id="grid-container">
<div className="grid-sizer"></div>
<div className="gutter-sizer"></div>
{posts.map(post => (
<div className="grid-item {post.frontmatter.category}">
<Link to={post.fields.slug}>
<figure className="image">
<Img fluid={post.frontmatter.image.childImageSharp.fluid} />
<figcaption>
<h4 className="title is-4">{post.frontmatter.title}</h4>
<p className="grid-item-blurb">{post.frontmatter.description}</p>
</figcaption>
</figure>
</Link>
</div>
))}
</div>
</section>
)
}
}
FilterGrid.propTypes = {
data: PropTypes.shape({
allMarkdownRemark: PropTypes.shape({
edges: PropTypes.array,
}),
}),
}
export default () => (
<StaticQuery
query = {graphql`
query FilterGridQuery {
allMarkdownRemark (
sort: { fields: [frontmatter___date], order: DESC}
filter: { frontmatter: {templateKey: {eq: "recipe"}}}
) {
edges{
node{
id
frontmatter {
title
date
description
image {
childImageSharp {
resize(width: 1500, height: 1500) {
src
}
fluid(maxWidth: 786) {
...GatsbyImageSharpFluid
}
}
}
}
fields {
slug
}
}
}
}
}
`}
render={(data, count) => <FilterGrid data={data} count={count} />}
/>
)
我只是想使用 Isotope.js 因为我以前用过它,但如果有更好的方法,请告诉我!这让我发疯!
提前致谢!
在这一行
const posts = this.props.data.allMarkdownRemark.node
您不是要 allMarkdownRemark.edges
吗? allMarkdownRemark.node
绝对是未定义的。
我正在使用 Gatsby 构建一个博客,我正在尝试实现一个带有过滤器的砖石网格来显示我的帖子。过去,我是通过使用 Isotope.js 来做到这一点的,所以我又使用了它。但是,它并没有真正起作用。我对 React 还是很陌生,所以我不知道哪里出了问题。
我收到此错误:TypeError: Cannot read property 'map' of undefined
import React from 'react';
import Img from 'gatsby-image';
import { Link, StaticQuery } from 'gatsby';
import Isotope from "isotope-layout/js/isotope";
import PropTypes from 'prop-types';
class FilterGrid extends React.Component {
constructor(props) {
super(props);
this.onFilterChange = this.onFilterChange.bind(this);
}
// Click Function
onFilterChange = (newFilter) => {
if (this.iso === undefined) {
this.iso = new Isotope('#grid-container', {
itemSelector: '.grid-item',
layoutMode: "fitRows",
percentPosition: true,
fitRows: {
gutter: '.gutter-sizer'
}
});
}
if(newFilter === '*') {
this.iso.arrange({ filter: `*` });
} else {
this.iso.arrange({ filter: `.${newFilter}` });
}
}
render() {
const posts = this.props.data.allMarkdownRemark.node
return(
// Filter Buttons
<section className="section">
<div className="button-group filter-button-group grid-filters">
<div className="tabs is-centered is-toggle">
<ul id="portfolio-flters">
<li data-filter="*" onClick={() => {this.onFilterChange("*")}}>All</li>
<li data-filter="brandy" onClick={() => {this.onFilterChange("brandy")}}>Brandy</li>
<li data-filter="cachaça" onClick={() => {this.onFilterChange("cachaça")}}>Cachaça</li>
<li data-filter="gin" onClick={() => {this.onFilterChange("gin")}}>Gin</li>
<li data-filter="mexcal" onClick={() => {this.onFilterChange("mezcal")}}>Mezcal</li>
<li data-filter="rum" onClick={() => {this.onFilterChange("rum")}}>Rum</li>
<li data-filter="tequila" onClick={() => {this.onFilterChange("tequila")}}>Tequila</li>
<li data-filter="whiskey" onClick={() => {this.onFilterChange("whiskey")}}>Whiskey</li>
<li data-filter="vodka" onClick={() => {this.onFilterChange("vodka")}}>Vodka</li>
</ul>
</div>
</div>
<div className="grid" id="grid-container">
<div className="grid-sizer"></div>
<div className="gutter-sizer"></div>
{posts.map(post => (
<div className="grid-item {post.frontmatter.category}">
<Link to={post.fields.slug}>
<figure className="image">
<Img fluid={post.frontmatter.image.childImageSharp.fluid} />
<figcaption>
<h4 className="title is-4">{post.frontmatter.title}</h4>
<p className="grid-item-blurb">{post.frontmatter.description}</p>
</figcaption>
</figure>
</Link>
</div>
))}
</div>
</section>
)
}
}
FilterGrid.propTypes = {
data: PropTypes.shape({
allMarkdownRemark: PropTypes.shape({
edges: PropTypes.array,
}),
}),
}
export default () => (
<StaticQuery
query = {graphql`
query FilterGridQuery {
allMarkdownRemark (
sort: { fields: [frontmatter___date], order: DESC}
filter: { frontmatter: {templateKey: {eq: "recipe"}}}
) {
edges{
node{
id
frontmatter {
title
date
description
image {
childImageSharp {
resize(width: 1500, height: 1500) {
src
}
fluid(maxWidth: 786) {
...GatsbyImageSharpFluid
}
}
}
}
fields {
slug
}
}
}
}
}
`}
render={(data, count) => <FilterGrid data={data} count={count} />}
/>
)
我只是想使用 Isotope.js 因为我以前用过它,但如果有更好的方法,请告诉我!这让我发疯!
提前致谢!
在这一行
const posts = this.props.data.allMarkdownRemark.node
您不是要 allMarkdownRemark.edges
吗? allMarkdownRemark.node
绝对是未定义的。