Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

349
Vistas
How to have a parent/global Resource in React-Admin?

Context:

The database structure of my application starts at the Company level, a user may be part of more than one company, and he may switch Companies at any point, every other Resource resides inside Company

Every time the user switches company, the whole application changes, because the data changes, it's like a Global Filter, by companyId, a resource that needs to be loaded first and all other depend on it.

So for example, to get the Projects of a Company, the endpoint is /{companyId}/projects

The way I've tried to do this is using a React Context in the Layout, because I need it to encompass the Sidebar as well.

It's not working too well because it is querying userCompanies 4 times on startup, so I'm looking either for a fix or a more elegant solution

Another challenge is also to relay the current companyId to all child Resources, for now I'm using the filter parameter, but I don't know how I will do it in Show/Create/Edit

companyContext.js

const CompanyContext = createContext()

const companyReducer = (state, update) => {
  return {...state, ...update}
}

const CompanyContextProvider = (props) => {
  const dataProvider = useDataProvider();
  const [state, dispatch] = useReducer(companyReducer, {
    loading : true,
    companies : [],
    firstLoad : false
  })

  useEffect(() => {
    if(!state.firstLoad) { //If I remove this it goes on a infinite loop
      //This is being called 3 times on startup
      console.log('querying user companies')
      dataProvider.getList('userCompanies')
        .then(({data}) =>{
          dispatch({
            companies: data,
            selected: data[0].id, //Selecting first as default
            loading: false,
            firstLoad: true
          })
        })
        .catch(error => {
          dispatch({
            error: error,
            loading: false,
            firstLoad: true
          })
        })
    }
  })

  return (
    <CompanyContext.Provider value={[state, dispatch]}>
      {props.children}
    </CompanyContext.Provider>
  )
}

const useCompanyContext = () => {
  const context = useContext(CompanyContext);
  return context
}

layout.js

const CompanySelect = ({companies, loading, selected, callback}) => {
  const changeCompany = (companyId) => callback(companyId)

  if (loading) return <div>Loading...</div>
  if (!companies || companies.length < 1) return <div>You are not part of a company</div>

  return (
    <select value={selected} onChange={(evt) => changeCompany(evt.target.value)}>
      {companies.map(company => <option value={company.id} key={company.id}>{company.name}</option>)}
    </select>
  )
}

const CompanySidebar = (props) => {
  const [companyContext, dispatch] = useCompanyContext();
  const {companies, selected, loading, error} = companyContext;

  const changeCompany = (companyId) => {
    dispatch({
      selected : companyId
    })
  }

  return (
    <div>
      <CompanySelect companies={companies} selected={selected} loading={loading} callback={changeCompany}/>
      <Sidebar {...props}>
        {props.children}
      </Sidebar>
    </div>
  )  
}

export const MyLayout = (props) => {
  return (
    <CompanyContextProvider>
      <Layout {...props} sidebar={CompanySidebar}/>
    </CompanyContextProvider>
  )
};

app.js

const ProjectList = (props) => {
  const [companyContext, dispatch] = useCompanyContext();
  const {selected, loading} = companyContext;
  if(loading) return <Loading />;
  //The filter is how I'm passing the companyId
  return (
    <List {...props} filter={{companyId: selected}}>
      <Datagrid rowClick="show">
        <TextField sortable={false} source="name" />
        <DateField sortable={false} source="createdAt" />
      </Datagrid>
    </List>
  );
};

const Admin = () => {
  return (
    <Admin
      authProvider={authProvider}
      dataProvider={dataProvider}
      layout={MyLayout}
    >
      <Resource name="projects" list={ProjectList}/>
    </Admin>
  );
};
over 4 years ago · Santiago Trujillo
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda