Search code examples
javascriptreactjsdestructuring

Destructured object as function parameter


I don’t understand the parameter of const Posts below. I’m fairly new to node/React. Is it a destructured parameter object? Or is it just an object being passed as a parameter?

getPosts and post are showing as undefined. But I don’t understand where the parameter object is being passed from into the function...

Full code here: https://github.com/bradtraversy/devconnector_2.0/blob/master/client/src/components/posts/Posts.js

Thanks in advance!!

import React, { Fragment, useEffect } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import Spinner from '../layout/Spinner';
import PostItem from './PostItem';
import PostForm from './PostForm';
import { getPosts } from '../../redux/actions/post';

const Posts = ({ getPosts, post: { posts, loading } }) => {
  useEffect(() => {
    getPosts();
  }, [getPosts]); ```


Solution

  • So Posts is a React Function component.

    All Function components will receive a props object as its first argument.

    const Posts = (props) => { /* ... */ }
    

    props will always be an object containing the props that were passed into it when the component was rendered, for example:

    import Posts from './path/to/Posts'
    
    function SomeParentComponent() {
      return <Posts limit={10} categories={{news:true, sports:false}} />
    }
    

    In this case props will be an object that looks like this:

    {
      limit : 10,
      categories : {
        news : true,
        sports : false,
      }
    }
    

    You can of course destructure the props object in your component:

    const Posts = (props) => {
      const { 
       limit,
       categories
      } = props
      // ... other stuff
    }
    

    But you can go even further and do what's called "unpacking" in order to destructure nested properties

    const Posts = (props) => {
      const { 
       limit,
       categories : {
         sports,
         news
       }
      } = props
      // ... other stuff
    }
    

    Lastly, instead of doing that in the function body, you can destructure and unpack objects in-line where the arguments are for the same result.

    const Posts = ({limit, categories:{news,sports}}) => {
      // ... other stuff
    }
    

    Which is what your code sample is doing.

    It appears it's expecting the parent component to pass in a function as the getPosts prop, which when called will first set posts.loading to true, load the posts, then set posts.loading to false. Ex:

    function SomeParentComponent() {
      const [loading, setLoading] = useState(false)
      const [posts, setPosts] = useState([])
    
      const loadPosts = useCallback(async () => {
        setLoading(true)
        const loadedPosts = await loadPostsSomehow()
        setPosts([posts, ...loadedPosts])
        setLoading(false)
      }, [])
      return <Posts getPosts={loadPosts} post={{posts, loading}} />
    }
    
    

    Make sure to use useCallback to get a memoized callback here or you will get stuck in an infinite loop

    **EDIT**

    After actually looking at the link provided, it's slightly different actually. Instead of the post object being provided by the parent component, it's actually provided by redux, but the logic is essentially the same. The difference is that instead of the parent component changing the loading and post state, it's done via redux state management.