简体   繁体   中英

How To Query Firestore to get Document by String Field (Search Engine Friendly Slug)

I have a Component in React called ShowArticle and I am trying to query for a single document in Firestore in my articles collection by a string field called slug so that I can format my URLs as //myhost.com/article/show/:slug where slug is the matching, unique string in my Firestore.

As my Route I have:

<Route exact path="/article/show/:slug" component={ShowArticle} />

So I am getting the :slug parameter correctly with const { slug } = props.match.params; inside of ShowArticle component.

When I query the Firestore for a slug that exists in my database I receive no data back from Firestore.

How do I retrieve an Article document by a unique string value for SEF URLs?

My ShowArticle Component is as follows:

 import React, { Component } from 'react'; import { connect } from 'react-redux'; import { compose } from 'redux'; import { firestoreConnect } from 'react-redux-firebase'; import { PropTypes } from 'prop-types'; import Article from "./Article"; class ShowArticle extends Component { render() { const { article } = this.props; if (article) { return ( <div> <Article key={article.id} title={article.title} date={article.date} body={article.body} /> </div> ); } else { return ( <div>Loading...</div> ) } } } ShowArticle.propTypes = { firestore: PropTypes.object.isRequired }; export default compose( firestoreConnect(props => { const { slug } = props.match.params; console.log(slug); return [ {collection: 'articles', storeAs: 'article', doc: slug } ] }), connect(({ firestore: { ordered } }, props) => ({ article: ordered.article && ordered.article[0] })) )(ShowArticle); 

In the callback to firestoreConnect() change doc: slug to queryParams: [ 'equalTo=' + slug ]

So you will end up with:

export default compose(
  firestoreConnect(props => {
    const { slug } = props.match.params;
    console.log(slug);
    return [
      {collection: 'articles', storeAs: 'article', queryParams: [ 'equalTo=' + slug ] }
    ]
  }),
  connect(({ firestore: { ordered } }, props) => ({
    article: ordered.article && ordered.article[0]
  }))
)(ShowArticle);

Reference http://react-redux-firebase.com/docs/queries.html#notParsed in the docs for the react-redux-firebase package.

Most probably you are using the latest version of React Router (v4+). Because in older React Router, it's the way to make available the id with the props. But in newer react-router library, you have to wrap the whole component with the "withRouter" higher-order component. It will pass updated match, location, and history props to the wrapped component whenever it renders.

At first, you have to import the withRouter.

import { withRouter } from "react-router";

Then you have to wrap it with withRouter.

 export default withRouter(compose(
  firestoreConnect(props => {
    const { slug } = props.match.params;
    console.log(slug);
    return [
      {collection: 'articles', storeAs: 'article', doc: slug }
    ]
  }),
  connect(({ firestore: { ordered } }, props) => ({
    article: ordered.article && ordered.article[0]
  }))
)(ShowArticle))

This works for me like a charm!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM