Javascript 组件如何向其同级发送消息而不将状态向上移动到组件树?

Javascript 组件如何向其同级发送消息而不将状态向上移动到组件树?,javascript,reactjs,babeljs,Javascript,Reactjs,Babeljs,我有一个“页面”组件,其中包含一个表单和一个列表。表单和列表是完全自包含且不相交的,只是在保存表单时,列表应该刷新 我的页面组件整体上如下所示: export default class PaymentsPage extends React.PureComponent { static propTypes = { bookingId: XPropTypes.stringOrNumber.isRequired, test: PropTypes.bool,

我有一个“页面”组件,其中包含一个表单和一个列表。表单和列表是完全自包含且不相交的,只是在保存表单时,列表应该刷新

我的页面组件整体上如下所示:

export default class PaymentsPage extends React.PureComponent {

    static propTypes = {
        bookingId: XPropTypes.stringOrNumber.isRequired,
        test: PropTypes.bool,
        stripePublishableKey: PropTypes.string,
        stripeUserId: PropTypes.string,
    };

    render() {
        return (
            <div>
                <ContentSection title="Enter Payment" storageKey="record-payment">
                    <RecordPaymentForm bookingId={this.props.bookingId} test={this.props.test} />
                </ContentSection>
                <ContentSection title="Previous Payments" storageKey="previous-payments">
                    <PreviousPaymentsTable bookingId={this.props.bookingId} test={this.props.test} stripePublishableKey={this.props.stripePublishableKey} stripeUserId={this.props.stripeUserId} />
                </ContentSection>
            </div>
        )
    }
}
导出默认类PaymentsPage扩展React.PureComponent{
静态类型={
bookingId:XPropTypes.stringOrNumber.isRequired,
测试:PropTypes.bool,
StripePublisableKey:PropTypes.string,
stripeUserId:PropTypes.string,
};
render(){
返回(
)
}
}
我的问题是,
RecordPaymentForm
如何向
PreviousPaymentsTable
发送消息,告诉它刷新

我不想将
RecordPaymentForm
的状态向上移动到
PaymentsPage
,因为我希望它保持独立

我没有使用flux/redux,现在也不打算使用它

我不想将RecordPaymentForm的状态升级到PaymentsPage,因为我希望它保持独立

如上所述,
RecordPaymentForm
如果要更新另一个组件,则它不是自包含的

处理这种情况的正确“反应”方式是在父组件(
PaymentsPage
)中存储
RecordPaymentForm
PreviousPaymentsTable
的共享状态,并将其传递给每个子组件

要从
RecordPaymentForm
更新
PaymentsPage
的状态,可以将函数作为道具传递,以充当处理程序。您可以在
PaymentsPage
中创建
handleChange
函数

export default class PaymentsPage extends React.PureComponent {

  static propTypes = {
    bookingId: XPropTypes.stringOrNumber.isRequired,
    test: PropTypes.bool,
    stripePublishableKey: PropTypes.string,
    stripeUserId: PropTypes.string,
  };

  handleChange(newValue) => {
    this.setState({
      someProp: newValue;
    });
  }

  render() {
    return (
      <div>
        <ContentSection title="Enter Payment" storageKey="record-payment">
          <RecordPaymentForm 
            bookingId={this.props.bookingId} 
            onChange={this.handleChange}
            someProp={this.props.someProp}
            test={this.props.test} 
          />
        </ContentSection>
        <ContentSection title="Previous Payments" storageKey="previous-payments">
          <PreviousPaymentsTable 
            bookingId={this.props.bookingId} 
            test={this.props.test} 
            someProp={this.props.someProp}
            stripePublishableKey={this.props.stripePublishableKey} 
            stripeUserId={this.props.stripeUserId} 
          />
        </ContentSection>
      </div>
    )
  }
}
导出默认类PaymentsPage扩展React.PureComponent{
静态类型={
bookingId:XPropTypes.stringOrNumber.isRequired,
测试:PropTypes.bool,
StripePublisableKey:PropTypes.string,
stripeUserId:PropTypes.string,
};
handleChange(新值)=>{
这是我的国家({
someProp:newValue;
});
}
render(){
返回(
)
}
}
我刚刚实现了大约3行代码。我认为它在这个特定的用例中会很好地工作

输入付款后,我将发布“paymentEntered”事件。任何感兴趣的组件(如my
PreviousPaymentsTable
)都可以订阅该主题,然后执行它需要的操作

此外,我甚至可以发布付款数据并将其弹出到我的付款列表中,这样我就不必进行完全刷新,但我无论如何都要这样做,因为我已经有了它的代码,我不介意新数据延迟50毫秒

这样,我的付款页面保持沉默,我可以将这些组件移动到任何页面,并在任何我愿意的地方重复使用它们,无论它们彼此有无,它们都将继续工作。

使用(面向事件的编程),兄弟姐妹之间的通信将如下所示:

组件发送者(发布者): 组件接收器(用户):
//如果您正在使用npm=>从“mufa”导入{on,fire};
const{on,fire}=window.mufa;
类RecordPaymentForm扩展React.Component{
onClick(事件){
火灾('addPayment',this.refs.item.value,this.refs.price.value);
}
render(){
返回(
添加
)
}
}
类PreviousPaymentsTable扩展了React.Component{
状态={记录:[]}
componentDidMount(){
在('addPayment',(项目、价格)=>{
this.setState({records:[…this.state.records,{item,price}]});
})
}
render(){
返回(
    { this.state.records.map((r,index)=>
  • {r.item}:{r.price}$
  • ) }
) } } 类应用程序扩展了React.Component{ render(){ 返回( ) } } ReactDOM.render(,document.querySelector('section'))


如果他们需要共享状态,这是合适的,但实际上他们并不需要。我只需要知道什么时候发生的事。我根本不需要那个事件的任何细节。把所有州都调高意味着我不能轻易地在其他地方重复使用我的付款单。看起来很像我提出的解决方案。mufa有什么优势吗?0。穆法宝贝1号。支持多条消息:如果您调用
fire('eventName',msg1,msg2,msg3)
您将在订阅服务器的回调中找到这3条消息
on('eventName',(msg1,msg2,msg3)=>)
。2.支持多个上下文:您可以创建另一个注册表:
import Mufa from'Mufa';常数m1=新的Mufa();m2=新的Mufa()。。。那么
m1.on
m2.fire
之间就没有关系了。。所以你有两种不同的背景。3 .
mufa
使用别名使代码更可读、更令人愉快:
on
sub
的别名,
fire
pub
的别名,
off
unsub
的别名无论如何,无论lib u使用什么,在事件处理程序中,通常都要调用
pub(fire)
。。。并在
componentDidMount
中调用
sub(on)
。。并在
组件中调用
unsub(关闭)
willunmount
import {fire} from 'mufa';

class RecordPaymentForm extends React.Component {

     // Assuming that the trigger to send the message is the following
     handleClick() {
       const message = 'this is a message from RecordPaymentForm';
       fire('sendSomething', message); 
     }
}
import {on} from 'mufa';

class PreviousPaymentsTable extends React.Component {

    componentDidMount() {
      on('sendSomething', (message) => {
         this.setState({recordPaymenetMessage: message});
      })
    }
}