Search code examples
javascriptreactjsreact-admin

react-admin pass props Main->layout->appBar


I have a react-admin app to manage users. Now I need to access some props in the custom header (appBar) that I created, but can't figure out how to get those accessible there.

Here some of the code.

Main.js

class Main extends React.Component
{

  render()
  {
    // const { }   = this.state;
    const { t } = this.props;
    const _this = this;

    return (
      <Admin dataProvider={dataProvider} {..._this.props.props} layout={CustomLayout}>
        <Resource name="users"
                  list={<UserList {..._this.props.props} />}
                  edit={<UserEdit {..._this.props.props} />}
                  create={<UserCreate {..._this.props.props} />}
        />
      </Admin>
    );
  }
}

export default Main;

From above code CustomLayout

const CustomLayout = (props) => <Layout
  {...props}
  appBar={Header}
  sidebar={Sidebar}
/>;

export default CustomLayout;

From above code Header

class Header extends React.Component {


  // ---> Lifecycle functions <---

  constructor(props)
  {
    super(props);

    // Here I need to access props... 
    
    this.selectCustomer = this.selectCustomer.bind(this);

    this.state = {
      selectedCustomerId: this.props.selectedCustomerId,
    };
  }


    return (
      <div>...</div>
    );
  }
}


export default Header;

How do I get props from Main -> CustomLayout -> Header? If in CustomLayout.js I change appBar={Header} to appBar={<Header {...props} />}, I get Uncaught Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.

I guess it needs to be the component-name. Is there any way to achieve this?


Solution

  • The preferred way here would be to use React functional components instead of classes and React.createContext() / React.useContext().

    import { createContext, useState } from 'react'
    export const MyContext = createContext(0)
    ...   
    const App = () => {       
      const [customerId, setCustomerId] = useState(123)
    
      return (
            <MyContext.Provider value={customerId} >
              <Admin ...>
              ...
              </Admin>
            </MyContext.Provider>      
      )
    }
    ...
    
    import { useContext } from 'react'
    import { AppBar } from 'react-admin'
    import { MyContext } from 'App'
    ...
    const CustomAppBar = (props: any) => {
      const value = useContext(MyContext)
      console.log('CustomAppBar, customerId:', value)
    
      return (<AppBar color="primary" {...props} >
          <TitlePortal />
          <div>{ 'ID:' + value }</div>
        </AppBar>)
    }