Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

why is useEffect running on first render?

I have a MERN react component that is going to show a toast to my user after they create a new group.

Here is my useEffect below

useEffect(() => {
    toast(
      <Fragment>
        New Group Created
      </Fragment>
    );
  }, [successCreate]);

I only want this useEffect to run AFTER my user creates a new group.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

It currently runs on first render, and after my user clicks the modal(child) then triggers the successCreate from redux(just creates a new group).

How can I make useEffect run only when successCreate is called.. NOT on first render AND successCreate

Here is my component

import React, { Fragment, useState, useEffect, useContext } from 'react';
import WizardInput from '../auth/wizard/WizardInput';
import {useDispatch, useSelector} from 'react-redux';
import { 
  Button,
  Card,
  CardBody,
  Form,
  Label,
  Input,
  Media,
  Modal,
  ModalBody,
  ModalHeader
 } from 'reactstrap';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import Select from 'react-select';
import { toast } from 'react-toastify';
import makeAnimated from 'react-select/animated';
import {listGroups, createGroup} from '../../actions/index';
//import { isIterableArray } from '../../helpers/utils';
import { CsvUploadContext } from '../../context/Context';
import chroma from 'chroma'


const StepOneForm = ({ register, errors, watch}) => {
  const { upload, setUpload } = useContext(CsvUploadContext);
  //const { handleInputChange } = useContext(CsvUploadContext);
  const [ createGroupModal, setCreateGroupModal ] = useState(false)
  const [newGroup, setNewGroup] = useState({
    title: ''
  })
  const dispatch = useDispatch();
  const groups = useSelector(state => state.groups)

  const groupCreate = useSelector((state) => state.groupCreate)
  const {success: successCreate} = groupCreate

  const animatedComponents = makeAnimated();

  useEffect(() => {
    dispatch(listGroups())
  }, [successCreate])

   useEffect(() => {
    toast(
      <Fragment>
        New Group Created
      </Fragment>
    );
  }, [successCreate]);

  const customStyles = {
    control: (base, state) => ({
      ...base,
      background: "light",
      // match with the menu
      borderRadius: state.isFocused ? "3px 3px 0 0" : 3,
      // Overwrittes the different states of border
      borderColor: state.isFocused ? "primary" : "light",
      // Removes weird border around container
      boxShadow: state.isFocused ? null : null,
      "&:hover": {
        // Overwrittes the different states of border
        borderColor: state.isFocused ? "blue" : "#2c7be5"
      }
    }),
    
    menu: base => ({
      ...base,
      // override border radius to match the box
      borderRadius: 0,
      // kill the gap
      marginTop: 0
    }),
    menuList: base => ({
      ...base,
      // kill the white space on first and last option
      padding: 0,
      color: 'f9fafd'
    }),
    option: (styles, { data, isDisabled, isFocused, isSelected }) => {
      const color = chroma(data.color);
      return {
        ...styles,
        backgroundColor: isDisabled
          ? null
          : isSelected
          ? data.color
          : isFocused,
        color: '232e3c',
      };
    }
  
  };

  const toggle = () => { setCreateGroupModal(!createGroupModal)}
  const closeBtn = (
    <button className="close font-weight-normal" onClick={toggle}>
      &times;
    </button>
  );
  const handleSubmit = (e) => {
    e.preventDefault()
      dispatch(createGroup(newGroup))
      setCreateGroupModal(false)
   };
 console.log(upload?.group)
   const handleChange = e => {
     setNewGroup({...newGroup, [e.target.name]: e.target.value})
   }


  return (
    <Fragment>
      <Media className="flex-center pb-3 d-block d-md-flex text-center mb-2">
        <Media body className="ml-md-4">
        
        </Media>
      </Media>

      <h4 className="mb-1 text-center">Choose Groups</h4>
          <p className=" text-center fs-0">These groups will contain your contacts after import</p>

          <Select
              name="group"
              required={true}
              className="mb-3"
              styles={customStyles}
              components={animatedComponents}
              innerRef={register({
                required: true
              })}
              closeMenuOnSelect={true}
              options={groups}
              getOptionLabel={({title}) => title}
              getOptionValue={({_id}) => _id}
              onChange={(_id) => setUpload({...upload, group: _id})}
              isMulti
              placeholder="select group"
              isSearchable={true}
              errors={errors}
            />
          <Button color="light" onClick={(() => setCreateGroupModal(true))} className="rounded-capsule shadow-none fs--1 ml- mb-0" >
                <FontAwesomeIcon icon="user-plus" />
                {` or create a new group`}
              </Button>
                <Modal isOpen={createGroupModal} centered toggle={() => setCreateGroupModal(!createGroupModal)}>
                <ModalHeader toggle={toggle} className="bg-light d-flex flex-between-center border-bottom-0" close={closeBtn}>
                Let's give the group a name
                  </ModalHeader>
                    <ModalBody className="p-0">
                        <Card>
                            <CardBody className="fs--1 font-weight-normal p-4"> 
                              <Card>
                                <CardBody className="fs--1 font-weight-normal p-4"> 
                                  <Form onSubmit={handleSubmit}>
                                    <Label for="title">Group Name:</Label>
                                      <Input value={newGroup.title.value} onChange={handleChange} className="mb-3" name="title" id="title"/>
                                      <Button block onClick={handleSubmit} color="primary" className="mb-3">Save</Button>
                                    </Form>
                                    </CardBody>
                                  </Card> 
                                <Button block onClick={() => setCreateGroupModal(false)}>close</Button>
                            </CardBody>
                        </Card>
                    </ModalBody>
                </Modal>
      

      <WizardInput
        type="textarea"
        label="or add number manually seperated by comma"
        placeholder="+17209908576, +18165009878, +19138683784"
        name="manual-add"
        rows="4"
        id="manual-add"
        innerRef={register({
          required: false
        })}
        errors={errors}
      />
    </Fragment>
  );
};

export default StepOneForm;

>Solution :

Is successCreate a boolean?

This would work:

useEffect(() => {
    if(!successCreate) return;

    toast(
      <Fragment>
        New Group Created
      </Fragment>
    );
  }, [successCreate]);

useEffect is always called when the dependencies change – on first render it is guaranteed to be called because there is nothing previous – this is the equivalent to componentDidMount

useEffect(() => {
   console.log('mounted');
},[]);
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading