Search code examples
javascriptreactjsdialogstatereact-props

How to send data from dialog back to parent container with react?


I have a react-big-calendar (The parent container), I have also a select which, the events of the calendar are fetched according to this select ( doctor name ) and I have a button when I click on it, the dialog will be appears (another component), on this dialog, I have a form to add an event after the select, when I post my API, I save it on local storage, but the event added doesn't appears on my calendar just after refresh the page and reselect the doctor name. But I want, when I click on the save button, will be added directly on the calendar and it will be appeared on the calendar.

My code of calendar is :

   import Popup from './Popup';
export default class Calendar extends Component {
constructor(props){
    super(props);
    this.state = {
      events : [],
      open: false,
}}
componentDidMount = () => {
    fetch(process.env.REACT_APP_API_BACKEND_YET+'get_liste_praticien.php')
      .then(Response => Response.json())
      .then(data => {
        this.setState ({ praticiens : data })
        localStorage.setItem('Liste de praticiens ', JSON.stringify(this.state.praticiens))
    })
}
fetchData = (nom,identifiant_user) => {
    this.setState({
      events: [],
      evtStorage:[],
      prevEvents:[], 
      evtBackend:[]
    })
      fetch(process.env.REACT_APP_API_BACKEND+'get_liste_planning')
        .then(Response => Response.json())
        .then(data => {
          let evts = data.ListeResult;
          for (let i = 0; i < evts.length; i++) {
            evts[i].start = moment(evts[i].start).toDate();
            evts[i].end = moment(evts[i].end).toDate();
           if(evts[i].typeplanning === '0') this.setState({isConges:true})
            this.state.events.push(evts[i])
          }                   
          this.setState({
            evtBackend: evts,
            events:  evts
          })
          localStorage.setItem("Liste de planning de " + nom, JSON.stringify(this.state.events));
        }) 
        const evtCached1 = JSON.parse(localStorage.getItem('Liste récente de planning de ' + nom));
        if(evtCached1 !== null) {
          for (let j = 0; j < evtCached1.length; j++) {
            evtCached1[j].start = moment(evtCached1[j].start).toDate();
            evtCached1[j].end = moment(evtCached1[j].end).toDate();
            if(evtCached1[j].typeplanning === '0') this.setState({isConges:true})
            this.state.events.push(evtCached1[j]);
          } 
          this.setState({
            events:this.state.events,
          });
          localStorage.removeItem("Liste de planning de " + nom);
        }}
// For the select
handlePraticienChange = id_user => {
    this.setState({ 
      openPopupAjout: true,
      id_user: id_user 
    },() => {
      this.state.praticiens.map((praticien)=> {
          if(this.state.id_user === praticien.id_user){
            this.setState ({ nom_user: praticien.nom_user})
           this.fetchData(praticien.nom_user, praticien.identifiant_user);
          }
      })
      }
    );
  }
// for the popup
 ModalAjoutb = (ref) => {
    if (ref) {
      this.ajoutb = ref.handleAjouterb;
    } else {
      this.ajoutb = null;
    }
  }
render() {

    return (
<div>
    <button className="bp3-button bp3-icon-add-to-artifact .bp3-fill" tabIndex="0" onClick={() => this.ajoutb(this.state.id_user, this.state.events)}>Add event</button>
    <Select  onChange={this.handlePraticienChange} value={this.state.id_user}>
        {this.state.praticiens.map((praticien) =>
            <Option key={praticien.id_user} value={praticien.id_user}>{praticien.nom_user}</Option>
        )}
    </Select>
    <DragAndDropCalendar
        selectable
        localizer={localizer}
        events={this.state.events} 
        views={['month','week','day']}
        defaultView="week"
        culture = 'fr'
    />
    <Popup ref={this.ModalAjoutb} id_user={this.state.id_user} events={this.state.events} />
</div>
);
}}

My code of dialog is :

export default class Popup extends Component {
constructor(props){
    super(props);
    this.state = {
      events : [],
}}
handleAjouterb = (id_user) => {
    this.setState({
      openPopupAjout: true,
      id_user,
    }, () => {
        this.fetchingPopup(this.state.id_user, this.state.identifiant_user, this.state.nom_user)
    });
  }
fetchingPopup = (id_user, identifiant_user, nom_user) =>{
    const praticiensCached = JSON.parse(localStorage.getItem('Liste de praticiens '));
    for (let j = 0; j < praticiensCached.length; j++) {
      if(id_user === praticiensCached[j].id_user){
        identifiant_user = praticiensCached[j].identifiant_user;
        this.setState ({ nom_user: praticiensCached[j].nom_user })
    }
}
handleValider = event => {
    event.preventDefault();
    const praticiensCached = JSON.parse(localStorage.getItem('Liste de praticiens '));
    for (let j = 0; j < praticiensCached.length; j++) {
      if(this.state.id_user === praticiensCached[j].id_user)
        this.state.identifiant_user = praticiensCached[j].identifiant_user;
    }

      const formData = new FormData();

      formData.append('identifiant_user', this.state.identifiant_user);
      formData.append('heuredebut', this.state.tranchesC[0].startC);
      formData.append('heurefin', this.state.tranchesC[0].endC);
      formData.append('libelleconge', this.state.libelle);
      axios({
        method: 'post',
        url: process.env.REACT_APP_API_BACKEND+'add_event_docteur',
        data: formData,
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json',
        }
      })
      .then(() => {
        fetch(process.env.REACT_APP_API_BACKEND+'get_liste_planning/start='+moment().startOf('isoweek').subtract(14,'days').toJSON()+'&end='+moment().endOf('isoweek').add(2,'months').toJSON()+'&identifiant_user='+this.state.identifiant_user)
          .then(Response => Response.json())
          .then(data => {
            let evts = data.ListeResult;
            for (let i = 0; i < evts.length; i++) {
              evts[i].start = moment(evts[i].start).toDate();
              evts[i].end = moment(evts[i].end).toDate();
              this.state.events.push(evts[i])
            }                   
            this.setState({
              events:  this.state.events
            }, ()=> {
              localStorage.setItem('Liste récente de planning de ' + this.state.nom_user, JSON.stringify(this.state.events));
              localStorage.removeItem("Liste de planning de " + this.state.nom_user);
              localStorage.setItem("Liste de planning de " + this.state.nom_user, JSON.stringify(this.state.events));
            })
          })
       })
}

render() {

    return (
<div>
    <Dialog
        icon="application"
        onClose={this.handleClose}
        title="Organisation des plannings du docteur"
        {...this.state}
        isOpen={this.state.openPopupAjout}>
           <Input id="libelle" style={{ width: '480px' }} value={this.state.libelle} onChange={this.handleInputChange('libelle')}/>       
            <label className="pt-label .modifier"><strong>Date</strong></label>
            <LocaleProvider locale={fr_FR}>
                <RangePicker id="date" name= "date"  locale="fr" placeholder={["Date de début","Date de fin"]} separator="-" onChange={this.handleDateCChange}
                    value={this.state.dateIC} format="DD/MM/YYYY" allowClear={false}/> 
            </LocaleProvider>
            <label className="pt-label .modifier"> <strong>Heure de début</strong></label>
            <Time value={el.startC} onChange={time => this.handleKeyboardStartCChange(i, time)} style={heure} disableUnderline={true} inputComponent={TextMaskCustom}
                    endAdornment={ <InputAdornment position="end" style={{opacity:'0.4'}}> <IconButton   onClick={() => this.openDialogC(i, el.startC, "startC")}><i  style={{fontSize:'18px'}} className="zmdi zmdi-alarm" /></IconButton>  </InputAdornment>}
            />
            <label className="pt-label .modifier"> <strong>Heure de fin</strong></label>
            <Time value={el.endC} onChange={time => this.handleKeyboardEndCChange(i, time)} style={heure} disableUnderline={true} inputComponent={TextMaskCustom}
                    endAdornment={ <InputAdornment position="end" style={{opacity:'0.4'}}> <IconButton  onClick={() => this.openDialogC(i, el.endC, "endC")}><i  style={{fontSize:'18px'}} className="zmdi zmdi-alarm" /></IconButton></InputAdornment> }/>

            <Clock maxWidth="xs" open={this.state.isOpenC} onBackdropClick={this.closeDialogC}>
            <TimePicker  mode="24h" value={this.createDateFromTextValueC(this.state.datePickerValueC)} onChange={this.handleDialogCChange}/>
            <DialogActions> <ButtonOk onClick={this.closeDialogC} color="primary"> Ok </ButtonOk></DialogActions>
            </Clock>
                <AnchorButton style={{display:'inline-block'}} intent={Intent.SUCCESS} onClick={this.handleValider}>Valider</AnchorButton>

</div>
);
}}

I want to refresh the list of my events and appear my event added on the calendar afer post form on the popup and not after the refresh of the page and I will reselect the doctor.

How can I fix it ?


Solution

  • Don't save events in your state, in Popup access the events directly from props.

    In your Calendar, create a function that'll update the state.

    updateEvents = (events, callback = () => {}) => {
      this.setState(
        {
          events
        },
        callback
      );
    };
    
    <Popup updateEvents={this.updateEvents} ref={this.ModalAjoutb} id_user={this.state.id_user} events={this.state.events} />
    

    Popup

    export default class Popup extends Component {
      constructor(props) {
        super(props);
      }
    
      handleAjouterb = id_user => {
        this.setState(
          {
            openPopupAjout: true,
            id_user
          },
          () => {
            this.fetchingPopup(
              this.state.id_user,
              this.state.identifiant_user,
              this.state.nom_user
            );
          }
        );
      };
      fetchingPopup = (id_user, identifiant_user, nom_user) => {
        const praticiensCached = JSON.parse(
          localStorage.getItem('Liste de praticiens ')
        );
        for (let j = 0; j < praticiensCached.length; j++) {
          if (id_user === praticiensCached[j].id_user) {
            identifiant_user = praticiensCached[j].identifiant_user;
            this.setState({ nom_user: praticiensCached[j].nom_user });
          }
        }
        handleValider = event => {
          event.preventDefault();
          const praticiensCached = JSON.parse(
            localStorage.getItem('Liste de praticiens ')
          );
          for (let j = 0; j < praticiensCached.length; j++) {
            if (this.state.id_user === praticiensCached[j].id_user)
              this.state.identifiant_user = praticiensCached[j].identifiant_user;
          }
    
          const formData = new FormData();
    
          formData.append('identifiant_user', this.state.identifiant_user);
          formData.append('heuredebut', this.state.tranchesC[0].startC);
          formData.append('heurefin', this.state.tranchesC[0].endC);
          formData.append('libelleconge', this.state.libelle);
          axios({
            method: 'post',
            url: process.env.REACT_APP_API_BACKEND + 'add_event_docteur',
            data: formData,
            headers: {
              'Content-Type': 'application/json',
              Accept: 'application/json'
            }
          }).then(() => {
            fetch(
              process.env.REACT_APP_API_BACKEND +
                'get_liste_planning/start=' +
                moment()
                  .startOf('isoweek')
                  .subtract(14, 'days')
                  .toJSON() +
                '&end=' +
                moment()
                  .endOf('isoweek')
                  .add(2, 'months')
                  .toJSON() +
                '&identifiant_user=' +
                this.state.identifiant_user
            )
              .then(Response => Response.json())
              .then(data => {
                let evts = data.ListeResult;
                for (let i = 0; i < evts.length; i++) {
                  evts[i].start = moment(evts[i].start).toDate();
                  evts[i].end = moment(evts[i].end).toDate();
                }
                this.props.updateEvents(evts, () => {
                  localStorage.setItem(
                    'Liste récente de planning de ' + this.state.nom_user,
                    JSON.stringify(evts)
                  );
                  localStorage.removeItem(
                    'Liste de planning de ' + this.state.nom_user
                  );
                  localStorage.setItem(
                    'Liste de planning de ' + this.state.nom_user,
                    JSON.stringify(evts)
                  );
                });
              });
          });
        };
      };
    
      render() {
        return (
          <div>
            <Dialog
              icon="application"
              onClose={this.handleClose}
              title="Organisation des plannings du docteur"
              {...this.state}
              isOpen={this.state.openPopupAjout}
            >
              <Input
                id="libelle"
                style={{ width: '480px' }}
                value={this.state.libelle}
                onChange={this.handleInputChange('libelle')}
              />
              <label className="pt-label .modifier">
                <strong>Date</strong>
              </label>
              <LocaleProvider locale={fr_FR}>
                <RangePicker
                  id="date"
                  name="date"
                  locale="fr"
                  placeholder={['Date de début', 'Date de fin']}
                  separator="-"
                  onChange={this.handleDateCChange}
                  value={this.state.dateIC}
                  format="DD/MM/YYYY"
                  allowClear={false}
                />
              </LocaleProvider>
              <label className="pt-label .modifier">
                {' '}
                <strong>Heure de début</strong>
              </label>
              <Time
                value={el.startC}
                onChange={time => this.handleKeyboardStartCChange(i, time)}
                style={heure}
                disableUnderline={true}
                inputComponent={TextMaskCustom}
                endAdornment={
                  <InputAdornment position="end" style={{ opacity: '0.4' }}>
                    {' '}
                    <IconButton
                      onClick={() => this.openDialogC(i, el.startC, 'startC')}
                    >
                      <i style={{ fontSize: '18px' }} className="zmdi zmdi-alarm" />
                    </IconButton>{' '}
                  </InputAdornment>
                }
              />
              <label className="pt-label .modifier">
                {' '}
                <strong>Heure de fin</strong>
              </label>
              <Time
                value={el.endC}
                onChange={time => this.handleKeyboardEndCChange(i, time)}
                style={heure}
                disableUnderline={true}
                inputComponent={TextMaskCustom}
                endAdornment={
                  <InputAdornment position="end" style={{ opacity: '0.4' }}>
                    {' '}
                    <IconButton
                      onClick={() => this.openDialogC(i, el.endC, 'endC')}
                    >
                      <i style={{ fontSize: '18px' }} className="zmdi zmdi-alarm" />
                    </IconButton>
                  </InputAdornment>
                }
              />
              <Clock
                maxWidth="xs"
                open={this.state.isOpenC}
                onBackdropClick={this.closeDialogC}
              >
                <TimePicker
                  mode="24h"
                  value={this.createDateFromTextValueC(this.state.datePickerValueC)}
                  onChange={this.handleDialogCChange}
                />
                <DialogActions>
                  {' '}
                  <ButtonOk onClick={this.closeDialogC} color="primary">
                    {' '}
                    Ok{' '}
                  </ButtonOk>
                </DialogActions>
              </Clock>
              <AnchorButton
                style={{ display: 'inline-block' }}
                intent={Intent.SUCCESS}
                onClick={this.handleValider}
              >
                Valider
              </AnchorButton>
          </div>
        );
      }
    }