title: Component Elements Re render & duplicate, but fix on refresh
body: <p>I am creating an app which can display projects, this project has a few child components and server-side functions running when a user creates a new project. This results in the props changing which causes the ProjectList to refresh which is fine but it then also produces two of the submitted project when in the database it shows one and when you refresh it displays one.</p>
  
  <p><a href="https://i.stack.imgur.com/FhfJI.png" rel="nofollow noreferrer">Screenshot of duplicated project entry</a></p>
  
  <p><a href="https://i.stack.imgur.com/r5Tin.png" rel="nofollow noreferrer">After page refresh</a></p>
  
  <p>As it works after refresh it makes me think its something to do with the state?</p>
  
  <p>So I have a Dashboard component - > ProjectList -> ProjectListDetails</p>
  
  <p>Dashboard code </p>
  
  <pre><code>import React, { Component } from "react";
  import { connect } from "react-redux";
  import { firestoreConnect } from "react-redux-firebase";
  import ProjectList from "../Projects/ProjectList";
  import { compose } from "redux";
  import CreateProject from "../Projects/CreateProject";
  import { Redirect } from "react-router-dom";
  
  class Dashboard extends Component {
    render() {
      const { projects, auth, profile, organisations } = this.props;
      if (!auth.uid) return &lt;Redirect to="/signin" /&gt;;
      //is the logged in user an Organisation or Single account?
      const isOrg =
        profile.isOrg === true ? (
          &lt;p&gt;Organisation Account&lt;/p&gt;
        ) : (
          &lt;p&gt;Single Account&lt;/p&gt;
        );
  
      return (
        &lt;div className="container"&gt;
          &lt;div className="row home-header-row"&gt;
            &lt;div className="col-md-12 section text-center"&gt;
              {isOrg}
              &lt;br&gt;&lt;/br&gt;
  
              &lt;CreateProject organisations={organisations} /&gt;
              &lt;ProjectList
                projects={projects}
                authID={auth.uid}
                profile={profile}
              /&gt;
            &lt;/div&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      );
    }
  }
  
  const mapStateToProps = state =&gt; {
    return {
      projects: state.firestore.ordered.projects,
      auth: state.firebase.auth,
      profile: state.firebase.profile,
      notifications: state.firestore.ordered.notifications,
      organisations: state.firestore.ordered.organisations
    };
  };
  
  export default compose(
    connect(mapStateToProps),
    firestoreConnect([
      { collection: "projects", orderBy: ["totalEntries", "desc"] },
      { collection: "organisations", orderBy: ["time", "desc"] },
      { collection: "notifications", limit: 5, orderBy: ["time", "desc"] }
    ])
  )(Dashboard);
  </code></pre>
  
  <p>Project List Component :</p>
  
  <pre><code>import React, { Component } from "react";
  import ProjectListDetails from "./ProjectListDetails";
  
  import "firebase/firestore";
  
  class ProjectList extends Component {
    // shouldComponentUpdate(nextProps, nextState) {
    //     return this.props.projects !== nextProps.projects;
    //   }
  
    render() {
      return (
        &lt;div className="project-list section"&gt;
          {this.props.projects &amp;&amp;
            this.props.projects.map(project =&gt; {
              const projectId =
                project.authorID +
                project.createdAt.toDate().toLocaleTimeString("it-it") +
                project.title;
  
              return (
                &lt;&gt;
                  {project.canView.includes(this.props.profile.email) ||
                  project.authorEmail.includes(this.props.profile.email) ? (
                    &lt;ProjectListDetails
                      project={project}
                      profile={this.props.profile}
                      projectId={projectId}
                    &gt;&lt;/ProjectListDetails&gt;
                  ) : null}
                &lt;/&gt;
              );
            })}
        &lt;/div&gt;
      );
    }
  }
  
  export default ProjectList;
  </code></pre>
  
  <p>ProjectListDetails Component</p>
  
  <pre><code>import React, { Component } from "react";
  
  import EditProject from "./EditProjects";
  import DeleteProject from "./DeleteProject";
  import { Link } from "react-router-dom";
  import ProjectSummary from "./ProjectSummary";
  
  class ProjectListDetails extends Component {
    render() {
      console.log("printing project : " + this.props.project.title);
  
      return (
        &lt;div className="row" key={this.props.project.id}&gt;
          &lt;div className="col-md-12" key={this.props.project.projectID}&gt;
            &lt;button
              className="btn btn-secondary dropdown-toggle project-options"
              type="button"
              id="dropdownMenuButton"
              data-toggle="dropdown"
              aria-haspopup="true"
              aria-expanded="false"
            &gt;
              Options
            &lt;/button&gt;
            &lt;div
              className="dropdown-menu"
              aria-labelledby="dropdownMenuButton"
              id={this.props.project.projectID}
            &gt;
              &lt;EditProject /&gt;
              &lt;DeleteProject /&gt;
            &lt;/div&gt;
  
            &lt;Link
              to={"/project/" + this.props.project.id}
              key={this.props.project.id}
              profile={this.props.profile}
              projectId={this.props.projectId}
            &gt;
              &lt;ProjectSummary
                projectId={this.props.projectId}
                project={this.props.project}
                key={this.props.project.id}
                authID={this.props.authID}
              /&gt;
            &lt;/Link&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      );
    }
  }
  
  export default ProjectListDetails;
  </code></pre>
  
  <p>CreateProject Component</p>
  
  <pre><code>import React, { Component } from "react";
  import { connect } from "react-redux";
  import { createProject } from "../../Store/Actions/projectActions";
  import Button from "react-bootstrap/Button";
  import Modal from "react-bootstrap/Modal";
  
  // import ReactQuill from 'react-quill'
  // import 'react-quill/dist/quill.snow.css'
  // import renderHTML from 'react-render-html';
  
  class CreateProject extends Component {
    state = {
      title: "",
      content: "",
      projectAmount: 0,
      commentAmount: 0,
      hideModal: false,
      showModal: "",
      show: false,
      setShow: false,
      canView: [],
      organisation: ""
    };
  
    handleChange = e =&gt; {
      this.setState({
        [e.target.id]: e.target.value
      });
    };
  
    handleSubmit = e =&gt; {
      e.preventDefault();
  
      this.setState({ canView: [] });
  
      this.props.organisations &amp;&amp;
        this.props.organisations.map(organisation =&gt; {
          if (organisation.canView.includes(this.props.profile.email)) {
            const orgUser = organisation.canView.map((item, key) =&gt;
              this.state.canView.push(item)
            );
            return orgUser;
          }
          return null;
        });
      this.props.createProject(this.state);
  
      document.getElementById("title").value = "";
      document.getElementById("content").value = "";
    };
  
    handleClose = () =&gt; {
      this.setState({
        show: false
      });
    };
    handleShow = () =&gt; {
      this.setState({
        show: true
      });
    };
  
    render() {
      return (
        &lt;&gt;
          &lt;Button
            className="btn btn-primary"
            variant="primary"
            onClick={this.handleShow}
          &gt;
            New Project
          &lt;/Button&gt;
  
          &lt;Modal show={this.state.show} onHide={this.handleClose}&gt;
            &lt;Modal.Header closeButton&gt;
              &lt;Modal.Title&gt;New Project&lt;/Modal.Title&gt;
            &lt;/Modal.Header&gt;
            &lt;Modal.Body&gt;
              &lt;form onSubmit={this.handleSubmit}&gt;
                &lt;div className="form-group"&gt;
                  &lt;input
                    onChange={this.handleChange}
                    className="form-control"
                    type="text"
                    id="title"
                    placeholder="Project Title"
                  /&gt;
                &lt;/div&gt;
                &lt;div className="form-group"&gt;
                  &lt;textarea
                    onChange={this.handleChange}
                    className="form-control"
                    id="content"
                    rows="3"
                    placeholder="Project Content (can add some more options here later)"
                  &gt;&lt;/textarea&gt;
                &lt;/div&gt;
                &lt;Modal.Footer&gt;
                  &lt;Button variant="secondary" onClick={this.handleClose}&gt;
                    Close
                  &lt;/Button&gt;
                  &lt;Button
                    type="submit"
                    variant="primary"
                    onClick={this.handleClose}
                  &gt;
                    Save Changes
                  &lt;/Button&gt;
                &lt;/Modal.Footer&gt;
              &lt;/form&gt;
            &lt;/Modal.Body&gt;
          &lt;/Modal&gt;
        &lt;/&gt;
      );
    }
  }
  
  const mapStateToProps = state =&gt; {
    return {
      projects: state.firestore.ordered.projects,
      auth: state.firebase.auth,
      profile: state.firebase.profile,
      organisations: state.firestore.ordered.organisations
    };
  };
  
  const mapDispatchToProps = dispatch =&gt; {
    return {
      createProject: project =&gt; dispatch(createProject(project))
    };
  };
  
  export default connect(mapStateToProps, mapDispatchToProps)(CreateProject);
  </code></pre>
  
  <p>Project Action</p>
  
  <pre><code>export const createProject = project =&gt; {
    return (dispatch, getState, { getFirebase, getFirestore }) =&gt; {
      // make async call to database
      const firestore = getFirestore();
      const profile = getState().firebase.profile;
      const authorId = getState().firebase.auth.uid;
      const createdAt = new Date();
      const convertedDate = createdAt.toLocaleTimeString("it-it");
      const printFirstName =
        profile.isOrg === true ? profile.orgFirstName : profile.firstName;
      const printLastName =
        profile.isOrg === true ? profile.orgLastName : profile.lastName;
      const projectId = authorId + convertedDate + project.title;
      const orgName = profile.organisation ? profile.organisation : "";
  
      //this.state.project.createdAt.toDate().toLocaleTimeString('it-it') + this.state.project.title
  
      firestore
        .collection("projects")
        .doc(projectId)
        .set({
          ...project,
          authorFirstName: printFirstName,
          authorLastname: printLastName,
          authorID: authorId,
          authorEmail: profile.email,
          canView: project.canView,
          canEdit: [profile.email],
          createdAt: createdAt,
          projectID: projectId,
          organisation: orgName,
          permalink: "/project/" + projectId
        })
        .then(() =&gt; {
          dispatch({ type: "CREATE_PROJECT", project });
        })
        .catch(err =&gt; {
          dispatch({ type: "CREATE_PROJECT_ERROR", err });
        });
      //
    };
  };
  </code></pre>
  
  <p>ProjectReducer</p>
  
  <pre><code>const initState = {};
  
  const projectReducer = (state = initState, action) =&gt; {
    switch (action.type) {
      case "CREATE_PROJECT":
        return state;
      case "DELETE_PROJECT":
        console.log("Project Deleted", action.project);
        return state;
      case "CREATE_PROJECT_ERROR":
        console.log("Create project error", action.err);
        return state;
      case "DELETE_PROJECT_ERROR":
        console.log("Delete project error", action.err);
        return state;
      default:
        return state;
    }
  };
  
  export default projectReducer;
  </code></pre>
  
  <p>Firebase Function</p>
  
  <pre><code>exports.projectInnerEntries = functions.firestore
    .document("projects/{projectId}")
    .onWrite((change, context) =&gt; {
      const newValue = change.after.data();
      var projectAmount = newValue.projectAmount;
      var commentAmount = newValue.commentAmount;
      // var totalEntries = projectAmount + commentAmount;
      const notification = {
        projects: projectAmount,
        comments: commentAmount,
        total: projectAmount + commentAmount
      };
  
      return admin
        .firestore()
        .collection("projects")
        .doc(newValue.projectID)
        .update({
          totalEntries: notification.total
        });
    });
  </code></pre>