Javascript 您好,我无法使用React中的自定义观察者类将逻辑与UI解耦

Javascript 您好,我无法使用React中的自定义观察者类将逻辑与UI解耦,javascript,reactjs,request,observer-pattern,Javascript,Reactjs,Request,Observer Pattern,所以我阅读了关于高阶组件的文档,认为重构我糟糕的monolit组件是个好主意 我的计划: 订阅可观测值 获取数据并将其存储在地图中 通知更改并以某种方式更新UI(我是react新手,我知道有很多方法可以使用redux、mobx等)。但是我的小项目的目的是学习,我希望尽可能地保持事物的本地性(用于UI libs的ecxept) 下面的任何代码都可能是错误的 这是我的观察者课程,自1994年以来一直保持不变 export default class Observable { //observer

所以我阅读了关于高阶组件的文档,认为重构我糟糕的monolit组件是个好主意

我的计划:

  • 订阅可观测值
  • 获取数据并将其存储在地图中
  • 通知更改并以某种方式更新UI(我是react新手,我知道有很多方法可以使用redux、mobx等)。但是我的小项目的目的是学习,我希望尽可能地保持事物的本地性(用于UI libs的ecxept)
  • 下面的任何代码都可能是错误的 这是我的观察者课程,自1994年以来一直保持不变

    export default class Observable { //observer
      listeners = new Set();
      constructor(value) {
        this.value = value;
      }
      get() {
        return this.value;
      }
      set(newValue) {
        if (newValue !== this.value) {
          this.notify();
        }
      }
      subscribe(listener) {
        this.listeners.add(listener);
      }
      unsubscribe(listener) {
        this.listeners.delete(listener);
      }
      notify() {
        for (const listener of this.listeners) {
          listener();
        }
      }
    }
    
    这是管理我观察到的类的订阅的高阶组件

    import React from "react";
    
    export default function withSubscription(WrappedComponent, api) {
      return class extends React.Component {
        constructor(props) {
          super(props);
          this.state = {
            data: api.observableMapData //observable object
          };
          this.handleChange.bind(this);
        }
    
        handleChange() {
          this.setState({
            data: api.observableMapData
          });
          console.log("changed data") //never actually saw it in the console
        }
    
        componentDidMount() {
          //observable object->getterfield->subscribe
          api.fetchData();
          api.observableMapData.dataSourceMap.subscribe(this.handleChange);  
        }
    
        componentWillUnmount() {
          //observable object->getterfield->unsubscribe
          api.observableMapData.dataSourceMap.unsubscribe(this.handleChange);
        }
    
        render() {
          return <WrappedComponent data={this.state.data} {...this.props} />;
        }
      };
    }
    
    
    和包装器函数

    const api = new Api();
    const TicketFormWithSubscription = withSubscription(
        UiFormController,
        api
      );
    
    export default TicketFormWithSubscription;
    
    我就这样拿地图

    export default class ApiService {
      
      observableMapData = new DataSourceMap();
      //singleton
      constructor() {
        if (!ApiService._instance) {
    
          ApiService._instance = this;
         // this.fetchData();
        }
        return ApiService._instance;
      }
    
    async fetchData() {
        let tmpMap = new Map();
         for (let value of this.observableMapData.dataSources) {
          let data = await this.getAllItems(value[1]);
          console.log(data);
          tmpMap.set(value[1], data)
        }
        //setter
        this.observableMapData.setDataSourceMap = tmpMap;   
        console.log(JSON.stringify(this.observableMapData + " fetched"));
      }
    
    ...
    }
    
    
    因此,主要的问题是组件的加载速度比数据的检索速度快。当我打开Autocomplete时,会出现一个错误,因为值未定义,并且在获取数据后不会更新

    最后,这里是道具流程

  • 至UIC(韩德尔事件)
  • 构造函数(道具){
    超级(道具);
    此.state={
    observableMap:this.props.data,
    confimOpen:错,
    ....
    }
    ...
    render(){
    常量newProps={
    项目:this.props.data.dataSourceMap.get('projects'),
    组织:this.props.data.dataSourceMap.get('organizations'),
    }
    返回(
    );
    }
    
    和materialUI自动完成组件

    <Autocomplete
                options={props.organizations.items}
                margin="dense"
                getOptionLabel={(option) => `${option.name}`}
                renderInput={(params) => (
    ...
    
     <Autocomplete
                options={props.projects.items}
                margin="dense"
                getOptionLabel={(option) => `${option.name}`}
                renderInput={(params) => (
    ...
    
    `${option.name}`}
    renderInput={(参数)=>(
    ...
    `${option.name}`}
    renderInput={(参数)=>(
    ...
    
    我觉得我的方法很老,但可行,提前感谢你的新鲜眼光,我明白了 只需使用挂钩或 acync componentDidMount()

    constructor(props) {
        super(props);
        
        this.state = {
          observableMap: this.props.data,
          confimOpen: false,
          ....
    }
    ...
    
    render() {
    
        const newProps = { 
            projects : this.props.data.dataSourceMap.get('projects'),
            organizations: this.props.data.dataSourceMap.get('organizations'),
        }
    
        return (
          <TicketFormUi
            {...newProps}
          />
        );
      }
    
    <Autocomplete
                options={props.organizations.items}
                margin="dense"
                getOptionLabel={(option) => `${option.name}`}
                renderInput={(params) => (
    ...
    
     <Autocomplete
                options={props.projects.items}
                margin="dense"
                getOptionLabel={(option) => `${option.name}`}
                renderInput={(params) => (
    ...