【问题标题】:How to send data from dialog back to parent container with react?如何通过反应将数据从对话框发送回父容器?
【发布时间】:2019-10-13 17:01:16
【问题描述】:

我有一个react-big-calendar(父容器),我还有一个选择,日历的事件是根据这个选择(医生姓名)获取的,当我点击它时我有一个按钮,对话框将出现(另一个组件),在此对话框中,我有一个表单可以在选择后添加一个事件,当我发布我的 API 时,我将其保存在本地存储中,但添加的事件不会出现在我的日历上刷新页面并重新选择医生姓名。 但是我想,当我点击保存按钮时,会直接添加到日历上,并且会出现在日历上。

我的日历代码是:

   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>
);
}}

我的对话框代码是:

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>
);
}}

我想刷新我的事件列表,并在弹出窗口的发布表单之后而不是在刷新页面之后显示我的事件添加到日历中,我将重新选择医生。

我该如何解决?

【问题讨论】:

  • 将 localStorage 添加到 state,然后通过 props 发送 state!
  • @RadonirinaMaminiaina 你能告诉我如何编码吗?
  • 我添加了一个伪代码
  • @RadonirinaMaminiaina 请检查我的答案

标签: javascript reactjs dialog state react-props


【解决方案1】:

我认为,您可以使用如下代码实现它:

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}>
  }
}

进入你的组件

export default class ComponentB extends Component {
    render () {
    // display the value of foo prop
    return <div>{this.props.foo}</div>
  }
}

注意:您始终可以尝试直接从ComponentB 获取您的localStorage 的内容(也许使用ComponentDidUpdate ???),但我向您展示的方式更好。

【讨论】:

  • 我尝试foo (nom) { this.setState({ events: localStorage.getItem('Liste récente de planning de ' + nom) })},但它不起作用,这是同样的问题。
  • 你怎么称呼你的 foo?
  • 我在 Popup 组件上调用我的 foo,例如:this.state = { events: this.props.foo }
  • 这样设置状态是一种不好的做法。你应该使用setState ...在你的弹出代码中,只需调用this.foo('your name')
  • 我收到TypeError: _this.props.foo is not a function
【解决方案2】:

您是否正在寻找类似的东西

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}/>
}
}

【讨论】:

  • 但我希望在我从弹出窗口添加事件后,它会直接出现在我的日历上,而不是在刷新页面并重新选择医生后
【解决方案3】:

为什么不使用 React 的上下文特性 React Context API

context.js

export const store = {
  something: 'val',
  setSomeThing : () => {}
};

export const CalContext = React.createContext(
  store // default value
);

pop-up.js

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;

calender.js

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>
   );}
}

【讨论】:

    【解决方案4】:

    您可以使用 React Context API 或 Redux。

    但是,如果您不想要这些,您可以在子组件中使用作为方法的 prop,这样父组件就可以捕获事件。它类似于 Angular 2+ 的输出机制。

    这是一个例子:

    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
    }
    

    【讨论】:

      【解决方案5】:

      在您的父组件中,即&lt;Calendar/&gt;,您可以为 say 定义一个方法

      HandleNewDataFromPopup(data) {
         this.setState({newData: data})
      }
      

      并将此方法作为道具传递给 Popup 组件

      <Popup HandleNewDataFromPopup={this.HandleNewDataFromPopup}/>
      

      在您的&lt;Popup/&gt; 组件中,在获取调用成功的方法handleValider 中,您可以调用方法HandleNewDataFromPopup (this.props.HandleNewDataFromPopup) 来填充父组件中的数据

      handleValider() {
        // on axios success
        this.props.HandleNewDataFromPopup(data)
      }
      

      这能回答你的问题吗?

      【讨论】:

        【解决方案6】:

        不要在你的 state 中保存事件,在 Popup 中直接从 props 访问事件。

        在您的日历中,创建一个将更新状态的函数。

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

        弹出窗口

        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>
            );
          }
        }
        

        【讨论】:

          猜你喜欢
          • 2017-04-27
          • 1970-01-01
          • 2020-04-02
          • 2018-12-23
          • 2018-07-14
          • 2011-12-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多