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 ?
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>
);
}
}
I think, you can achieve it using code like this:
export default ComponentA extends Component {
// set localStorage to bar state value
// via click or whatever ...
foo () {
this.setState({
bar: localStorage.getItem('bar')
})
}
render () {
// send the value of state to ComponentB
return <ComponentB foo={this.state.bar}>
}
}
Into your component
export default class ComponentB extends Component {
render () {
// display the value of foo prop
return <div>{this.props.foo}</div>
}
}
Note: You can always try to get the content of your localStorage
directly from the ComponentB
(Maybe using ComponentDidUpdate???) but the way I show you is better.
Why not you use context Feature of React React Context API
export const store = {
something: 'val',
setSomeThing : () => {}
};
export const CalContext = React.createContext(
store // default value
);
import {CalContext} from './context';
class Popup extends React.Component {
updateValue = () => {
this.context.setSomeThing('new_value');
}
render() {
let calContext = this.context;
return (
<button onClick={this.updateValue} >
{calContext.something}
</button>
);
}
}
Popup.contextType = CalContext;
export default Popup;
import {CalContext} from './context';
import Popup from './pop-up'
class calender extends React.Component {
constructor(props) {
this.state = {
something : 'value'
}
}
setSomeThing = (newVal) => {
// actual set something code.
this.setState({something : newVal});
}
render() {
let contextVal = { something : this.state.something, setSomeThing : this.setSomeThing }
// The entire state is passed to the provider
return (
<CalContext.Provider value={contextVal}>
<Popup />
</CalContext.Provider>
);}
}
Are you looking for something like this
class ComponentB extends React.Component{
render(){
this.props.setInLocalStorage();
const value = localStorage.getItem("testA");
return <div>
This is componentB{value}
</div>}
}
class ComponentA extends React.Component{
setInLocalStorage = ()=>{
localStorage.setItem('testA', 'Hello');
}
render(){
return <ComponentB setInLocalStorage={this.setInLocalStorage}/>
}
}
You can either use React Context API or Redux.
But if you don't want those, you can use a prop that is a method in your child component, so the parent can capture the event. It is similar Output mechanic from Angular 2+.
Here is an example:
const ChildComponent = (onSelect = () => {}) => {
return <div onClick={() => onSelect('You selected me')}>Child Component</div>
}
const ParentComponent = () => {
return <ChildComponent onSelect={message => console.log(message)} /> // You selected me
}
In your parent component i.e <Calendar/>
you can a define a method for say
HandleNewDataFromPopup(data) {
this.setState({newData: data})
}
and pass this method as a prop in the Popup component
<Popup HandleNewDataFromPopup={this.HandleNewDataFromPopup}/>
and in your <Popup/>
component in the method handleValider
on sucess of fetch call you can call the method HandleNewDataFromPopup (this.props.HandleNewDataFromPopup)
to populate the data in your parent component
handleValider() {
// on axios success
this.props.HandleNewDataFromPopup(data)
}
Does this answer your question?
©2020 All rights reserved.