3

I have created an Ionic React app using Ionic 5 tab template.

I want to pass an object from App component to tab component.

Is there any way to do it ?

Tab1 and Tab2 are my tab components.

Note: I want this object to be used in both Tab components with two way data binding i.e. whenever that object is changed in one Tab component, it must be updated in second Tab component.I want to achieve it without using Redux or any third party library.

My App component is like below:

<IonApp>
    <IonReactRouter>
      <IonTabs>
        <IonRouterOutlet>
            <Route path="/tab1"
                    component=Tab1
                    exact={true} />
            <Route path="/tab2"
                    component=Tab2
                    exact={true} />
          <Route path="/" render={() => <Redirect to="/tab1" />} exact={true} />
        </IonRouterOutlet>
        <IonTabBar slot="bottom">
            <IonTabButton tab={"Title1"} href={"/tab1"}>
              <IonIcon icon={settings} />
              <IonLabel>{"Title1"}</IonLabel>
            </IonTabButton>
            <IonTabButton tab={"Title2"} href={"/tab2"}>
              <IonIcon icon={settings} />
              <IonLabel>{"Title2"}</IonLabel>
            </IonTabButton>
        </IonTabBar>
      </IonTabs>
  </IonReactRouter>
</IonApp>
Yuvraj Patil
  • 7,944
  • 5
  • 56
  • 56
  • Since you are using routing button, you may want something like `routing with props` which could be found here https://ionicframework.com/docs/react/navigation#url-parameters – keikai Mar 15 '20 at 03:47
  • I believe it would be making one way data communication. I want to use that object in both tabs and in two way communication without using Redux. – Yuvraj Patil Mar 15 '20 at 03:53
  • 2
    As far as I know, react **props isn't designed for two-way data communication** – keikai Mar 15 '20 at 03:55
  • React sends "data" down the tree. The pattern for sending "data" up the tree is through a callback that is passed down to descendants from ancestor, i.e. the callback is passed from parent to child. If you want the "data" in one component to reflect changes to it from another component then you need to loft the "data" to the closest common ancestor, or use *some* global state object, i.e. react context, or redux, mobx, etc... – Drew Reese Mar 15 '20 at 04:32

2 Answers2

2

you can use React.Context with React Hooks for simple state interactions between the tabs, you can then move up to React.useReducer

Below is a basic example using React.Context - Example on CodeSandbox.io

import React from "react";

// create the context
export const Context = React.createContext();

// create the context provider, we are using use state to ensure that
// we get reactive values from the context...
export const TheProvider = ({ children }) => {
  // the reactive values
  const [sharedValue, setSharedValue] = React.useState("initial");

  // the store object
  let state = {
    sharedValue,
    setSharedValue
  };

  // wrap the application inthe provider with the initialized context
  return <Context.Provider value={state}>{children}</Context.Provider>;
};

export default Context;

Wrap the application in the provider

import { TheProvider } from "./some-context";

const App: React.FC = () => {
  return (
    <IonApp>
      <TheProvider>
       {/* here the provider wraps the whole application to allow */}
       {/* access to the context that is defined */}
        <IonReactRouter>
          <IonTabs>
            <Route
              path="/"
              render={() => <Redirect to="/tab1" />}
              exact={true}
            />
            <IonRouterOutlet>
              <Route path="/tab1" component={Tab1} exact={true} />
              <Route path="/tab2" component={Tab2} exact={true} />
            </IonRouterOutlet>
            <IonTabBar slot="bottom">
              <IonTabButton tab={"Title1"} href={"/tab1"}>
                <IonLabel>{"Title1"}</IonLabel>
              </IonTabButton>
              <IonTabButton tab={"Title2"} href={"/tab2"}>
                <IonLabel>{"Title2"}</IonLabel>
              </IonTabButton>
            </IonTabBar>
          </IonTabs>
        </IonReactRouter>
      </TheProvider>
    </IonApp>
  );
};

And now an example use in a tab

const Tab2 = () => {
  // use react hooks to get the context and the information that is stored
  // in the context, the value and the function to modify the value
  const { sharedValue, setSharedValue } = React.useContext(AppContext);
  return (
    <IonPage>
      <IonHeader>
        <IonToolbar>
          <IonTitle>TAB ONE</IonTitle>
        </IonToolbar>
      </IonHeader>
      <IonContent>
        <>
          <h2>TAB TWO</h2>
          <div>{sharedValue}</div>
          <IonButton
            onClick={() =>
              setSharedValue("From Tab 2: " + new Date().getMilliseconds())
            }
          >
            Update Value
          </IonButton>
        </>
      </IonContent>
    </IonPage>
  );
};
Aaron Saunders
  • 33,180
  • 5
  • 60
  • 80
  • this gives me the problem as posted at https://stackoverflow.com/questions/66085880/ionic-react-type-is-not-assignable – Moblize IT Feb 10 '21 at 04:12
  • those are two different issues.... if you can post your code in codesandbox... fork my example, I can take a look – Aaron Saunders Feb 10 '21 at 20:06
1

you can use your Tab Component in render props of <Route> and pass your object in Tab Component.

<Route
  path="/tab1"
  exact={true}
  name="routeName"
  render={props => (
    <Tab1 object={yourObject}  />
  )} />

aslo you can pass all props like this <Tab1 {...props}/>.

Or you can use Redux https://react-redux.js.org/