Categories
Mastering Development

Error rendering react-redux functional component when data is deleted from firestore (useFirestoreConnect)

My ArticleList component is successfully getting & displaying the user’s list of articles from firestore when I first load the app. The user can click a “Remove Article” button, which successfully removes the article from the subcollection in firestore, but it causes an error in the rendering of the react component, which seems to still be trying to render the article that was just removed and is now null. Is there something else I can do to make my react component continuously listen to the firestore data? If possible, I’d like to keep this a functional component and use hooks rather than making it a class, but I’m still learning how to use react hooks and therefore struggling a bit.

Beginning of the ArticleList component:

const ArticleList = (props) => {
const firestore = useFirestore();
const userId = props.auth.uid;
useFirestoreConnect([
{
  collection: 'users',
  doc: userId,
  subcollections: [{collection: 'articles'}],
  storeAs: userId + '::articles'
}
]);
const myArticles = useSelector(state => state.firestore.data[`${userId}::articles`]);
const dispatch = useDispatch();
const removeArticle = useCallback(
articleId => dispatch(removeArticleFromFirebase({ firestore }, articleId)),
[firestore]
);

…then the return statement maps through myArticles such that each article is displayed as a list item with a button that includes onClick={() => {removeArticle(articleId);}}.

And the removeArticleFromFirebase action:

export const removeArticleFromFirebase = ({ firestore }, id) => {
return (dispatch, getState) => {
const userId = getState().firebase.auth.uid;
firestore
  .collection('users')
  .doc(userId)
  .collection('articles')
  .doc(id)
  .delete()
  .then(() => {
    console.log('Deleted article from firestore: ', id);
    dispatch({ type: 'REMOVE_ARTICLE', id });
  })
  .catch(err => {
    console.log('Error: ', err);
  });
};
}

I’ve tried adding useState and useEffect in the ArticleList as follows (and tried having the component’s return statement map through myArticlesState instead of myArticles), but no success:

const [myArticlesState, setMyArticlesState] = useState(myArticles);
useEffect(() => {
setMyArticlesState(myArticles);
}, [myArticles]);

Here are the package versions:

"dependencies": {
"css-loader": "^3.2.1",
"firebase": "^7.5.2",
"isomorphic-fetch": "^2.2.1",
"materialize-css": "1.0.0-rc.2",
"prop-types": "^15.7.2",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-redux": "^7.1.3",
"react-redux-firebase": "^3.0.5",
"react-router-dom": "^5.1.2",
"redux": "^3.7.2",
"redux-firestore": "^0.11.0",
"redux-thunk": "^2.2.0",
"style-loader": "^1.0.1",
"styled-jsx": "^3.2.4",
"uuid": "^3.3.3"
},

Note: I do not currently have this article list in overall app state/redux store/props at all. This is something I was thinking of trying next, but I decided to post my question first in case I can just use hooks in this component. No other components/parts of the app need access to this particular list.

Leave a Reply

Your email address will not be published. Required fields are marked *