Reputation: 769
I can't manage to pass props to my Outlet components in the new react-router v6. I tried the straightforward solution:
render() {
return (
<Outlet name="My name" />
);
}
And that correctly renders the child component, however no props are passed to the child. None of the examples provided by the React team (or anyone else for that matter) display Outlets with props, so I'm worried it's not actually a thing. Is there another way I'm not finding or am I using Output components incorrectly?
Edit: Seems there's no straightforward way to pass props, see answer below.
Upvotes: 59
Views: 83291
Reputation: 2329
When using functional component declare the name in the parent component like this.
function Parent() {
const const name='Your name'
return <Outlet context={[name]} />;
}
Then in the child component do this
//import this
import { useOutletContext } from "react-router-dom";
function Child() {
const [name] = useOutletContext();
return <p >{name}</p>;
}
Upvotes: 31
Reputation: 1099
This is now possible (from version 6.1.0) with the context prop
<Outlet context={}/>
Upvotes: 17
Reputation: 141
one way i did it and it works well is to create a reach context, if you know how to use react context, this will be easy for you.
In a separate file create Context.js to prevent require loop
const AdminStoreContext = React.createContext();
and then export it
export{AdminStoreContext}
then in another file create a consumer and provider of the context, and then import the context you've creates
import { AdminStoreContext } from "../../contexts";
class AdminStoreContextProvider extends React.Component {
constructor(props) {
super(props);
this.state = { ===vlaues you want to share }
}
render() {
return (
<AdminStoreContext.Provider
value={{
...this.state,//===spread the value you want to share
}}>
{
this.props.children
}
</AdminStoreContext.Provider>
);
}
}
const AdminStoreContextConsumer = AdminStoreContext.Consumer;
export { AdminStoreContextConsumer, AdminStoreContextProvider }
you can wrap your app with the context
<AdminStoreContextProvider>
<app/>
<AdminStoreContextProvider />
you can use either the consumer or the context to get the values for the purpose of Outlet, we use the context
once again import it
import { AdminStoreContext } from "../../contexts";
const route[{
path: 'consumer',
element: <MyMainComponent AdminStoreContext ={AdminStoreContext } />,
children: [
{ path: 'account', element: <MySubComponent1 /> },
{ path: 'purchaseHistory', element: <MySubComponent2 /> }
]
},
then in your MySubComponent1 or MySubComponent2
get the value from the props and use
const { AdminStoreContext } = props;
const context = React.useContext(AdminStoreContext )
and from the context you an get your values, hope this is helpfull
context.//get any value you put on the state
Upvotes: 2
Reputation: 1647
An alternative option here is to use Context API to share props from your parent view to your child view.
const Context = React.createContext({})
function ParentView () {
const outlet = useOutlet()
return (
<Context.Provider value={{ foo: 'bar' }}>
<h1>Parent View</h1>
{outlet}
</Context.Provider>
)
}
function ChildView () {
const props = React.useContext(Context)
return (
<div>child view {props.foo}</div>
)
}
Another option (untested) may be to use React.cloneElement
to clone outlet and add props to it.
Upvotes: 9
Reputation: 769
Unfortunately after digging for a while it looks like there's no straightforward way to do this and no plans to change it (at least for now), based on this GitHub issue's response https://github.com/ReactTraining/react-router/issues/7495.
Upvotes: 2