How do I use axios response in different components without using export?

前端 未结 1 1066
小鲜肉
小鲜肉 2021-01-26 03:42

As the tittle says, I would like to be able to use the same axios response for differents components. I have some restrictions like, I\'m onlyl able to use react by adding scrip

相关标签:
1条回答
  • 2021-01-26 04:13

    Here's a working example of how you might do it. I've tried to annotate everything with comments, but I'm happy to try to clarify if you have questions.

    // Fake response object for the store's "load" request
    const fakeResponse = {
      user: {
        fullName: "Carolina Ponce",
        roles: [
          { roleName: "administrator" },
          { roleName: "editor" },
          { roleName: "moderator" },
          { roleName: "generally awesome person" }
        ]
      }
    };
    
    // this class is responsible for loading the data
    // and making it available to other components.
    // we'll create a singleton for this example, but
    // it might make sense to have more than one instance
    // for other use cases.
    class UserStore {
      constructor() {
        // kick off the data load upon instantiation
        this.load();
      }
    
      // statically available singleton instance.
      // not accessed outside the UserStore class itself
      static instance = new this();
    
      // UserStore.connect creates a higher-order component
      // that provides a 'store' prop and automatically updates
      // the connected component when the store changes. in this
      // example the only change occurs when the data loads, but
      // it could be extended for other uses.
      static connect = function(Component) {
        // get the UserStore instance to pass as a prop
        const store = this.instance;
    
        // return a new higher-order component that wraps the connected one.
        return class Connected extends React.Component {
          // when the store changes just force a re-render of the component
          onStoreChange = () => this.forceUpdate();
    
          // listen for store changes on mount
          componentWillMount = () => store.listen(this.onStoreChange);
    
          // stop listening for store changes when we unmount
          componentWillUnmount = () => store.unlisten(this.onStoreChange);
    
          render() {
            // render the connected component with an additional 'store' prop
            return React.createElement(Component, { store });
          }
        };
      };
    
      // The following listen, unlisten, and onChange methods would
      // normally be achieved by having UserStore extend EventEmitter
      // instead of re-inventing it, but I wasn't sure whether EventEmitter
      // would be available to you given your build restrictions.
    
      // Adds a listener function to be invoked when the store changes.
      // Called by componentWillMount for connected components so they
      // get updated when data loads, etc.
      // The store just keeps a simple array of listener functions. This
      // method creates the array if it doesn't already exist, and
      // adds the new function (fn) to the array.
      listen = fn => (this.listeners = [...(this.listeners || []), fn]);
    
      // Remove a listener; the inverse of listen.
      // Invoked by componentWillUnmount to disconnect from the store and
      // stop receiving change notifications. We don't want to attempt to
      // update unmounted components.
      unlisten = fn => {
        // get this.listeners
        const { listeners = [] } = this;
    
        // delete the specified function from the array.
        // array.splice modifies the original array so we don't
        // need to reassign it to this.listeners or anything.
        listeners.splice(listeners.indexOf(fn), 1);
      };
    
      // Invoke all the listener functions when the store changes.
      // (onChange is invoked by the load method below)
      onChange = () => (this.listeners || []).forEach(fn => fn());
    
      // do whatever data loading you need to do here, then
      // invoke this.onChange to update connected components.
      async load() {
        // the loading and loaded fields aren't used by the connected
        // components in this example. just including them as food
        // for thought. components could rely on these explicit fields
        // for store status instead of pivoting on the presence of the
        // data.user object, which is what the User and Role components
        // are doing (below) in this example.
        this.loaded = false;
        this.loading = true;
    
        try {
          // faking the data request. wait two seconds and return our
          // hard-coded data from above.
          // (Replace this with your network fetch.)
          this.data = await new Promise(fulfill =>
            setTimeout(() => fulfill(fakeResponse), 2000)
          );
    
          // update the loading/loaded status fields
          this.loaded = true;
          this.loading = false;
    
          // call onChange to trigger component updates.
          this.onChange();
        } catch (e) {
          // If something blows up during the network request,
          // make the error available to connected components
          // as store.error so they can display an error message
          // or a retry button or whatever.
          this.error = e;
        }
      }
    }
    
    // With all the loading logic in the store, we can
    // use a much simpler function component to render
    // the user's name.
    // (This component gets connected to the store in the
    // React.createElement call below.)
    function User({ store }) {
      const { data: { user } = {} } = store || {};
    
      return React.createElement(
        "span",
        { className: "mr-2 d-none d-lg-inline text-gray-600 small" },
        user ? user.fullName : "loading (User)…"
      );
    }
    
    ReactDOM.render(
      // Connect the User component to the store via UserStore.connect(User)
      React.createElement(UserStore.connect(User), {}, null),
      document.getElementById("userDropdown")
    );
    
    // Again, with all the data loading in the store, we can
    // use a much simpler functional component to render the
    // roles. (You may still need a class if you need it to do
    // other stuff, but this is all we need for this example.)
    function Roles({ store }) {
      // get the info from the store prop
      const { data: { user } = {}, loaded, loading, error } = store || {};
    
      // handle store errors
      if (error) {
        return React.createElement("div", null, "oh noes!");
      }
    
      // store not loaded yet?
      if (!loaded || loading) {
        return React.createElement("div", null, "loading (Roles)…");
      }
    
      // if we made it this far, we have user data. do your thing.
      const roles = user.roles.map(rol => rol.roleName);
    
      return React.createElement(
        "a",
        { className: "dropdown-item" },
        roles.join(", ")
      );
    }
    
    ReactDOM.render(
      // connect the Roles component to the store like before
      React.createElement(UserStore.connect(Roles), {}, null),
      document.getElementById("dropdownRol")
    );
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
    
    <div id="userDropdown"></div>
    <div id="dropdownRol"></div>

    0 讨论(0)
提交回复
热议问题