Monday, November 29, 2021

Ninja - React Basic 10 - Props

Let's look at scenario where we have blogs in each page as we did it in Home page. Then we need to repeat the code block in every page.  

How to do it in a more better way.

we can make that bit of template as resusable component. eg: blog list component


{blogs.map(((blog) => (

                <div className='blog-preview' key={blog.id}>

                    <h2>{blog.title}</h2>

                    <p>Written by {blog.author}</p>

                </div>

            )))}


So if need to use that part in a category, tag or in any place we can just drop our component 'blog-list'.  We don't  need to repeat this total boiler plate code.


We use 'props'

with this template or component will be same, but data will be different. This helps to reuse.


1. create blog list component to hold the logic

2. create file 'BlogList.js' and create component BlogList


const BlogList = () => {

    return ();

}


export default BlogList;


3. Inside return copy paste the template we a re going to reuse. 

4. Before that let's  create a div , className=blog-list


const BlogList = () => {

    return (

        <div className='blog-list'>

            {blogs.map(((blog) => (

                <div className='blog-preview' key={blog.id}>

                    <h2>{blog.title}</h2>

                    <p>Written by {blog.author}</p>

                </div>

            )))}

        </div>

    );

}


5. Now inside home.js , we can simply use <BlogList />


return (

        <div className="home">

            <BlogList />

        </div>

    );


6. Now you get an error

'blogs' is not defined  no-undef


7. Because blogs data is not defined inside BlogList, we cannot use data defined inside another component.

8. How to solve ? There are few solutions.

8.1 Define data inside BlogList instead of Home

8.2 Use Props -> we pass this data from Home component into the BlogList component. 

9. We use second option props for three reasons


a. make BlogList component more resusable

b. We can still use data in the Home component, if needed inside Home component

c. Most important -> How to use props


10. Props is a way to pass data from a parent component to child component

11. Here Home is the parent and BlogList is the Child component

12. we are passing 'blogs' data into BlogList component

13. To do that, we create a property inside the <BlogList /> tag. You can call any name. Let's call 'blogs' as it's what we are passing.

<BlogList blogs= />

14. So this going to be a dynamic value, So curly braces.

<BlogList blogs={} />

15. value is 'blogs'. defined in top of the Home component.  

<div className="home">

            <BlogList blogs={blogs} />

 </div>

16. Now this is a prop. Now you will see an error

src\component\BlogList.js

  Line 4:14:  'blogs' is not defined  no-undef

  

17. This is cause of the next step, we are now going to use in BlogList. give tis as a parameter to BlogList


const BlogList = (blogs) => {

    return (

        <div className='blog-list'>

            {blogs.map(((blog) => (

                <div className='blog-preview' key={blog.id}>

                    <h2>{blog.title}</h2>

                    <p>Written by {blog.author}</p>

                </div>

            )))}

        </div>

    );

}


18. Now your error will disapear

19. Now we have another error


TypeError: blogs.map is not a function


20. getting an error


Failed to compile

./src/component/BlogList.js

SyntaxError: C:\Project\Project\Training\React\NetNinja\dojo-blog\src\component\BlogList.js: Identifier 'blogs' has already been declared. (1:18)


This is cause, i used 'blogs' instead of 'props' in BlogList(props)


const BlogList = (blogs) => {

    const blogs = this.props.blogs;

    return (

        <div className='blog-list'>

            {blogs.map(((blog) => (

                <div className='blog-preview' key={blog.id}>

                    <h2>{blog.title}</h2>

                    <p>Written by {blog.author}</p>

                </div>

            )))}

        </div>

    );

}


--------------------------------------

corrected code is

----------------------


const BlogList = (props) => {

    const blogs = this.props.blogs;

    return (

        <div className='blog-list'>

            {blogs.map(((blog) => (

                <div className='blog-preview' key={blog.id}>

                    <h2>{blog.title}</h2>

                    <p>Written by {blog.author}</p>

                </div>

            )))}

        </div>

    );

}


export default BlogList;



--------------------


21. But still get an error

TypeError: Cannot read properties of undefined (reading 'props')

BlogList

C:/Project/....../src/component/BlogList.js:2

  1 | const BlogList = (props) => {

> 2 |     const blogs = this.props.blogs;

  3 |     return (

  4 |         <div className='blog-list'>

  5 |             {blogs.map(((blog) => (

  

22. Reason for using 'this' keyword when accessing props 

const blogs = this.props.blogs;

23. remove 'this' and you will see page in the browser

24. Let's console out props and blogs

console.log(props,blogs);


25. you can see all the properties and blogs list.


Now we can pass multiple props

---------------------------

26. eg:title , it can be dynamic value, but here we just pass a string in Home.js

27. <BlogList blogs={blogs} title="All Blogs"/>  in Home.js

28. Now we can access this from BlogList and let's use in h2 tag and out put.


-----------------------------------------------------

const BlogList = (props) => {

    const blogs = props.blogs;

    const title = props.title;

    return (

        <div className='blog-list'>

            <h2>{title}</h2>

            {blogs.map(((blog) => (

                <div className='blog-preview' key={blog.id}>

                    <h2>{blog.title}</h2>

                    <p>Written by {blog.author}</p>

                </div>

            )))}

        </div>

    );

}

--------------------------------------------------


Further we can destructure 'props'

then we don't need const variables and can use straight away.

Code will looks like

---------------------------------------------------

const BlogList = ({blogs, title}) => {

    // const blogs = props.blogs;

    // const title = props.title;

    return (

        <div className='blog-list'>

            <h2>{title}</h2>

            {blogs.map(((blog) => (

                <div className='blog-preview' key={blog.id}>

                    <h2>{blog.title}</h2>

                    <p>Written by {blog.author}</p>

                </div>

            )))}

        </div>

    );

}

----------------------------------------------------


you can play with code and check what happens after changing name of the props and variables.

Yu can see , it will  still work without any issues.

const BlogList = (props1=> {
    const blogs = props1.blogs;
    const title = props1.title;
    return (
        <div className='blog-list'>
            <h2>{title}</h2>
            {blogs.map(((blog=> (
                <div className='blog-preview' key={blog.id}>
                    <h2>{blog.title}</h2>
                    <p>Written by {blog.author}</p>
                </div>
            )))}
        </div>
    );
}

No comments:

Post a Comment