Contexto:
La estructura de la base de datos de mi aplicación comienza en el nivel de la Company , un usuario puede ser parte de más de una empresa y puede cambiar de Companies en cualquier momento, todos los demás recursos residen dentro de Company
Cada vez que el usuario cambia de empresa, toda la aplicación cambia, porque los datos cambian, es como un filtro global , por companyId, un recurso que debe cargarse primero y todos los demás dependen de él.
Entonces, por ejemplo, para obtener los Projects de una Company , el punto final es /{companyId}/projects
La forma en que he tratado de hacer esto es usando un contexto de reacción en el diseño, porque también necesito que abarque la barra lateral.
No está funcionando demasiado bien porque está consultando userCompanies 4 veces al inicio , por lo que estoy buscando una solución o una solución más elegante.
Otro desafío es también transmitir el ID de la empresa actual a todos los recursos secundarios, por ahora estoy usando el parámetro de filtro, pero no sé cómo lo haré en Mostrar/Crear/Editar
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 }diseño.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> ) };aplicación.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> ); };