How to export multiple components in Reactjs


Usually we organize components React components in separate files. But for smaller components associated with component we are using need not be placed in operate file. In short it is possible to place multiple components in a single js file and export them.

 .....
  our component codes goes her

module.exports= {Post,Tags,Comments}

In the above fashion we can export the components and can import the components as follows

 const {Post,Tags,Comments} =from './components'

How to interact with input in Reactjs


With Browser route we can create beautiful responsive React app on the go. Most of the dynamic applications accepts some feed back from users. How do we get this done.

This will involve the following

  • Setting state for the each input element.
  • Attach it to the value property of the input.
  • Add a button event function and attach it to the render method.

Setting State

I have a one input text field and a button in the component.

import React, { Component } from "react"; 
 
class Comment extends Component {
  constructor(props) {
    super(props);    
    this.state = {      
    };
  }
  
  
  render() {
    return (
      <div className="form-group  m-2 p-2">
        <textarea
          placeholder="Comment here"
          class="form-control"          
          aria-describedby="inputSuccess5Status"
        />
        <button
          className="btn btn-primary m-1 p-2"        >
          Comment
        </button>         
      </div>
    );
  }
}

export default Comment;

In the above Comment component I have used bootstrap to beautify the form with one Text Area and button element. We need to create and attach a state for the Text Area in the constructor, also need to attach the new value with the state, whenever the user enter the comment. So we need to setState the comment in the on Change event handler.

  • Create state
  • Create event handler for on Change
  • attach them to the HTML tags
class Comment extends Component {
  constructor(props) {
    super(props);
    this.onChangeComment = this.onChangeComment.bind(this);
    this.onPostComment = this.onPostComment.bind(this);
     
    this.state = {
      comment: "",
    };
  }
  onChangeComment(e) {
    this.setState({ comment: e.target.value });
  }

  onPostComment(e) {
    try {
      
     console.log('Thank for using react form')
    } catch (error) {
      console.log(error);
    }
  }
  
  render() {
    return (
      <div className="form-group  m-2 p-2">
        <textarea
          placeholder="Comment here"
          class="form-control"
          value={this.state.comment}
          onChange={this.onChangeComment}
          aria-describedby="inputSuccess5Status"
        />
        <button
          className="btn btn-primary m-1 p-2"
          onClick={this.onPostComment}
        >
          Comment
        </button>
         <CommentCard  comments={this.props.comments}/>
      </div>
    );
  }
}

In the above code , created a state comment , event handlers for input and button and bind them in the constructor.

In the on Change event update the state so, each time the user update will change the state.

Finally attach the state and handlers to form elements ( button,Text Area).

Where did can I see the log(‘…’) result ?. well ,open your browser , ctrl+shift+I ( for developer tools) then go to console and you will see the message)

Following React posts deserve good read

How to populate multiple MongoDB objects on the same path in express-node


In Nodejs app we are using mongoose driver for MongoDB, a NoSql database with speed and accuracy. Mongo store data as series of JSON element call document and the collection of document is called a collection , same as table in DBMS.

According to the Mongoose doc Population is the process of automatically replacing the specified paths in the document with document(s) from other collection(s)

So we have the following Document , in which we want to populate user information . For simplicity I skipped some of the mongo

[
    { "tags": [
            "5fef1f5187a69346300003a8",
            "5fef1f5187a69346300003a9",
            "5fef1f5187a69346300003aa"
        ],
        "_id": "5fef1f5087a69346300003a7",
        "title": "Title post",
        "content": "It is a good practice to keep styles for different pages  in separate style sheets. Larger project this becomes more applicable. What you do when need to combine them in another ?",
        "user": "5fe4ab1e69b8d525c44ec293",
        "createdAt": "2021-01-01T13:10:40.468Z",
        "updatedAt": "2021-01-03T02:37:55.982Z",
        "__v": 11
    }
]

The document contains a list of posts with user information etc within the Tag ( not listed) . So the posts is a list of objects which should populate and inside each post have a user and list of tags object as well. Our task is to primarily populate the user object and the tags list.

We can do this right now using the find method of modal class accompanied by the populate command as follows

The tags array and the user belong to the posts path , so we have to repeat the population ( one for user and other for tags)

	const tid = req.params['tid']
			Tag.findById(tid).populate({
				path: 'posts',
				populate: {
					path: 'tags'
				},
				populate: {
					path: 'user',
					select: 'name'
				}
			}).populate({
				path: 'posts',
				populate: {
					path: 'tags',
					select: 'tagName'
				}
			}).exec((err, post) => {
				if (err) return handleError(err)
				console.log('tagged posts are ' + post);
				return res.status(200).send(post.posts)


			})

Result

[
    {
       
        "tags": [
            {
                "_id": "5fef1f5187a69346300003a8",
                "tagName": "Test"
            },
            {
                "_id": "5fef1f5187a69346300003a9",
                "tagName": "VM"
            },
            {
                "_id": "5fef1f5187a69346300003aa",
                "tagName": "JS"
            }
        ],
        "_id": "5fef1f5087a69346300003a7",
        "title": "Title post",
        "content": "It is a good practice to keep styles for different pages  in separate style sheets. Larger project this becomes more applicable. What you do when need to combine them in another ?",
        "user": {
            "_id": "5fe4ab1e69b8d525c44ec293",
            "name": "admin"
        },
        "createdAt": "2021-01-01T13:10:40.468Z",
        "updatedAt": "2021-01-03T02:37:55.982Z",
        "__v": 11
    }
]

In the above code we had used the populate inside another populate because the each posts had user element.

Following mongoose post also deserve a good read

How to populate selected fields in a mongo document path in expressjs


In Express-Nodejs app we are using mongoose driver for MongoDB, a NoSql database with speed and accuracy. Mongo store data as series of JSON element call document and the collection of document is called a collection , same as table in DBMS.

According to the Mongoose doc Population is the process of automatically replacing the specified paths in the document with document(s) from other collection(s)

So we have the following Document , in which we want to populate user information

[
    {
        "_id": "5fef1f5087a69346300003a7",
        "title": "Title post",
        "content": "It is a good practice to keep styles for different pages  in separate style sheets. Larger project this becomes more applicable. What you do when need to combine them in another ?",
        "user": "5fe4ab1e69b8d525c44ec293",
        "createdAt": "2021-01-01T13:10:40.468Z",
        "updatedAt": "2021-01-03T02:37:55.982Z",
        "__v": 11
    }
]

So the posts is a list of objects which should populate and inside each post have a user object as well. Our task is to primarily populate the specific user object fields.

We can do this right now using the find method of modal class accompanied by the populate command which specify the path and fields to populate as follows, also used a callback function.

const tid = req.params['tid']
			Tag.findById(tid).populate({
				path: 'posts',
				populate: {
					path: 'user',select:'name'
				}
			}).exec((err, post) => {
				if (err) return handleError(err)
				 
				return res.status(200).send(post.posts)


and the response will be as follows

[
    {
        "_id": "5fef1f5087a69346300003a7",
        "title": "Title post",
        "content": "It is a good practice to keep styles for different pages  in separate style sheets. Larger project this becomes more applicable. What you do when need to combine them in another ?",
        "user": {
            "password": "123",
            "posts": [
                "5feebf2b7e30080468ccd4c1",
                "5feec08a7e30080468ccd4c9",
                ]
            "_id": "5fe4ab1e69b8d525c44ec293",
            "name": "admin",             
        },
        "createdAt": "2021-01-01T13:10:40.468Z",
        "updatedAt": "2021-01-03T02:37:55.982Z",
        "__v": 11
    }
]

In the above code we had used the populate inside another populate because the each posts had user element.

We can use populate inside another one , find out how ? Next post will be on that !

Following mongoose post also deserve a good read

How to populate and display nested mongo objectin express-node route


In Nodejs app we are using mongoose driver for MongoDB, a NoSql database with speed and accuracy. Mongo store data as series of JSON element call document and the collection of document is called a collection , same as table in DBMS.

According to the Mongoose doc Population is the process of automatically replacing the specified paths in the document with document(s) from other collection(s)

So we have the following Document , in which we want to populate user information

[
    {
        "_id": "5fef1f5087a69346300003a7",
        "title": "Title post",
        "content": "It is a good practice to keep styles for different pages  in separate style sheets. Larger project this becomes more applicable. What you do when need to combine them in another ?",
        "user": "5fe4ab1e69b8d525c44ec293",
        "createdAt": "2021-01-01T13:10:40.468Z",
        "updatedAt": "2021-01-03T02:37:55.982Z",
        "__v": 11
    }
]

The document contains a list of posts with user information etc within the Tag ( not listed) . So the posts is a list of objects which should populate and inside each post have a user object as well. Our task is to primarily populate the user object.

We can do this right now using the find method of modal class accompanied by the populate command as follows

const tid = req.params['tid']
			Tag.findById(tid).populate({
				path: 'posts',
				populate: {
					path: 'user'
				}
			}).exec((err, post) => {
				if (err) return handleError(err)
				 
				return res.status(200).send(post.posts)


and the response will be as follows

[
    {
        "_id": "5fef1f5087a69346300003a7",
        "title": "Title post",
        "content": "It is a good practice to keep styles for different pages  in separate style sheets. Larger project this becomes more applicable. What you do when need to combine them in another ?",
        "user": {
            "password": "123",
            "posts": [
                "5feebf2b7e30080468ccd4c1",
                "5feec08a7e30080468ccd4c9",
                ]
            "_id": "5fe4ab1e69b8d525c44ec293",
            "name": "admin",
            "createdAt": "2020-12-24T14:52:14.364Z",
            "updatedAt": "2021-01-03T02:44:41.780Z",
            "__v": 108
        },
        "createdAt": "2021-01-01T13:10:40.468Z",
        "updatedAt": "2021-01-03T02:37:55.982Z",
        "__v": 11
    }
]

In the above code we had used the populate inside another populate because the each posts had user element.

Following mongoose post also deserve a good read

How to render mongo object in Reactjs


MongoDB objects are object Id of another document stored in the mongo database. Following is our sample mongo document we want to render in our React front end.

{    
    "_id": "5fef1f5087a69346300003a7",
    "title": "Title post",
    "content": "It is a good practice to keep styles for different pages  in separate style sheets. Larger project this becomes more applicable. What you do when need to combine them in another ?",
    "user": {    
        "_id": "5fe4ab1e69b8d525c44ec293",
        "name": "admin",
        "createdAt": "2020-12-24T14:52:14.364Z",
        "updatedAt": "2021-01-01T13:12:59.084Z",
        "__v": 106
    },
    "createdAt": "2021-01-01T13:10:40.468Z",
    "updatedAt": "2021-01-01T13:10:41.907Z",
    "__v": 3
}

Our task is to render the user object and access its properties

For simplicity I skip the rest of the component code.

render() {
    return (
      <div>
        <div className="card m-2 p-2">
          <h3>{this.state.post.title}</h3>
          <div>{this.state.post.content} </div>
          <div>  Posted By: {Object(this.state.post.user).name}            
     </div>
        </div>
      </div>
    );

React recognize sub document as filed, not as an object. So we have to convert the user to Object ( the highlighted line)

So far we have succeeded to render the MongoDB object

Following React posts deserve good read

How to render list of mongo objects in React component


We have already learned how to create mongo objects and array of objects, I put links below in case you need them.

Suppose we have the following document with array of tags which is a collection MongoDB objects. Our task is that render the list in the component.

{
    
    "tags": [
        {
            "posts": [
                "5fef1f5087a69346300003a7"
            ],
            "_id": "5fef1f5187a69346300003a8",
            "tagName": "Test",
            "createdAt": "2021-01-01T13:10:41.799Z",
            "updatedAt": "2021-01-01T13:10:41.855Z",
            "__v": 1
        },
        {
            "posts": [
                "5fef1f5087a69346300003a7"
            ],
            "_id": "5fef1f5187a69346300003a9",
            "tagName": "VM",
            "createdAt": "2021-01-01T13:10:41.804Z",
            "updatedAt": "2021-01-01T13:10:41.896Z",
            "__v": 1
        },
        {
            "posts": [
                "5fef1f5087a69346300003a7",
                "5fef1f7287a69346300003af",
                "5ff12f993ddcac34903623cd"
            ],
            "_id": "5fef1f5187a69346300003aa",
            "tagName": "JS",
            "createdAt": "2021-01-01T13:10:41.810Z",
            "updatedAt": "2021-01-03T02:44:43.120Z",
            "__v": 3
        }
    ],
    "_id": "5fef1f5087a69346300003a7",
    "title": "Title post",
    "content": "It is a good practice to keep styles for different pages  in separate style sheets. Larger project this becomes more applicable. What you do when need to combine them in another ?",
    "user": {        
        "_id": "5fe4ab1e69b8d525c44ec293",
        "name": "admin",
        "createdAt": "2020-12-24T14:52:14.364Z",
        "updatedAt": "2021-01-03T02:44:41.780Z",
        "__v": 108
    },
    "createdAt": "2021-01-01T13:10:40.468Z",
    "updatedAt": "2021-01-03T02:37:55.982Z",
    "__v": 11
}

How to access the list in React

It is best practice to store the list as separate state in a React component and not to access is directly as {post.tags.map(element=>().

Accessing the tags list using post.tags.map(element=>() cause Type and map error.

State

Add the state and from the API calls method ( I used the componetDidmount method) . I skipped the portion of component for simplicity

//contructor 
constructor(props) {
    super(props);

    this.state = {
      post: Object,
      tags: [],
      comments: [],
    };
  }

.....
.....
componentDidMount() {
    const { pid } = this.props.match.params;

    axios
      .get(`http://localhost:3005/post/${pid}`)
      .then((res) => {
        if (res.data) {
          this.setState({ post: res.data, tags: res.data.tags ,});
        }
      })
      .catch((error) => {
        console.log(error);
      });

       const id =`http://localhost:3005/comment/${pid}`
       
     axios
       .get(id)
       .then((response) => {        
         this.setState({comments:response.data})
       })
       .catch((e) => {
         console.log(e);
       });
  }

Rendering the List

We are ready to render the list inside <div> tags state using a the map with key.

{this.state.tags.map((element) => (
              <span
                className="badge badge-info m-1"
                key={element._id.toString()}
              >                
                {element.tagName}{" "}
              </span>
            ))}

we had successfully rendered the list of mongo objects.

Following React posts may help you

How to place custom route links in Reactjs component


Suppose you have a React application which uses link to navigate another route/page. How do we place the link ? . Let’s look at the post example.

const PostTitles= props=>(
  <div>
    <div>Date: {props.post.createdAt} </div>    
    <a href=`/post/${props.post._id}` >{props.post.title} </a>
  </div>
)

In the above code is a part of blogging web app, which consists of posts,uers,comments and tags components. In PostTitles component which shows title link of posts we used back tick ( `) to add variable. The back tick inside the render part may not work perfectly as in JavaScript.

Solution

So to make it work we have to add pair of extra curly braces ({}) as follows

const PostTitles= props=>(
  <div>
    <div>Date: {props.post.createdAt} </div>    
    <a href={`/post/${props.post._id}`} >{props.post.title} </a>
  </div>
)

Following React posts may help you

How to filter MongoDB object list in express-node app


MongoDB objects are object Id of another document stored in the mongo database. We can place multiple objects using list of object fields. A sample mongo object list as follows.

 "tags": [
        {
            "posts": [
                "5fef1f5087a69346300003a7"
            ],
            "_id": "5fef1f5187a69346300003a8",
            "tagName": "Test",
            "createdAt": "2021-01-01T13:10:41.799Z",
            "updatedAt": "2021-01-01T13:10:41.855Z",
            "__v": 1
        },
        {
            "posts": [
                "5fef1f5087a69346300003a7"
            ],
            "_id": "5fef1f5187a69346300003a9",
            "tagName": "VM",
            "createdAt": "2021-01-01T13:10:41.804Z",
            "updatedAt": "2021-01-01T13:10:41.896Z",
            "__v": 1
        },
        {
            "posts": [
                "5fef1f5087a69346300003a7",
                "5fef1f7287a69346300003af"
            ],
            "_id": "5fef1f5187a69346300003aa",
            "tagName": "JS",
            "createdAt": "2021-01-01T13:10:41.810Z",
            "updatedAt": "2021-01-01T13:11:15.561Z",
            "__v": 2
        }
    ],

We want to lookup at the above list of tags and make sure no more duplicate tags shown up in the future. A loop will do the job, using a filter we can do the same.

if (post.tags.filter(xtag => xtag == 'ABCD') == false) {
console.log(`No Tag found`);
} else {
console.log(`Tag already added`);
}

The filter uses a quick arrow function to filter result and return false when it failed to match the tag.

Following Mongo posts may help you

How to fix mongo object Type error in Reactjs


MongoDB objects are object Id of another document stored in the mongo database. Following is our sample mongo document we want to render in our React front end.

{    
    "_id": "5fef1f5087a69346300003a7",
    "title": "Title post",
    "content": "It is a good practice to keep styles for different pages  in separate style sheets. Larger project this becomes more applicable. What you do when need to combine them in another ?",
    "user": {    
        "_id": "5fe4ab1e69b8d525c44ec293",
        "name": "admin",
        "createdAt": "2020-12-24T14:52:14.364Z",
        "updatedAt": "2021-01-01T13:12:59.084Z",
        "__v": 106
    },
    "createdAt": "2021-01-01T13:10:40.468Z",
    "updatedAt": "2021-01-01T13:10:41.907Z",
    "__v": 3
}

In the above document we want to render the user object and the following code will cause an type error

For simplicity I skip the rest of the component code.

render() {
    return (
      <div>
        <div className="card m-2 p-2">
          <h3>{this.state.post.title}</h3>
          <div>{this.state.post.content} </div>
          <div> Posted By: {(this.state.post.user).name}            
     </div>
        </div>
      </div>
    );

TypeError: Cannot read property ‘name’ of undefined

Error Fix

React recognize sub document as filed, not as an object.To fix the error we have to convert the user to Object as follows.

render() {
    return (
      <div>
        <div className="card m-2 p-2">
          <h3>{this.state.post.title}</h3>
          <div>{this.state.post.content} </div>
          <div>  Posted By: {Object(this.state.post.user).name}            
     </div>
        </div>
      </div>
    );

Following React posts may help you