Reputation: 7022
Sometimes, the title of the Navigation Header will be determined by the content of the NavigationCard. E.g. in What's App, you will see the username and photo when you are in the chat window.
I'm wondering how to do this, since the NavigationHeader is the parent of the NavigationCard.
<NavigationAnimatedView
navigationState={navigationState}
style={styles.container}
onNavigate={(action) => {
if (action.type === 'back') {
navigateBack();
}
}}
renderOverlay={this._renderHeader.bind(this)}
renderScene={props => (
<NavigationCard
{...props}
key={props.scene.navigationState.key}
ref="sceneRef"
renderScene={this._renderScene.bind(this)}
/>
)}
/>
<NavigationHeader
{...props}
navigationState = {navigationState}
viewProps={props}
style={[styles.appbar]}
renderTitleComponent={() => this._renderTitle(route)}
renderLeftComponent={() => this._renderHeaderLeft(route)}
renderRightComponent={() => this._renderHeaderRight(route)}
/>
I tried creating a ref on the NavigationCard, so I can call the component containing the information, but that is not available yet in the renderTitleComponent method.
Upvotes: 3
Views: 703
Reputation: 2068
It works to change the title in the reducer. Keep in mind that routes.slice() does not clone the objects inside the array. The function below works with the standard header logic etc
case t.CHANGE_ROUTE_TITLE:{
let routes = state.routes.slice()
let i = routes.length - 1
routes[i] = {
...routes[i],
title: action.payload,
searchPlaceholder: 'Zoek in ' + action.payload
}
return {
...state,
index: routes.length - 1,
routes,
};
}
Upvotes: 0
Reputation: 4485
My solution to this problem is quite simple but I'm not sure if it's not too hacky. Only thing you need to change is reducer part, so you keep changes in one place. I just dynamically change title
from state as PUSH
/POP
action appears:
const initialState = {
index: 0,
routes: [
{key: 'cities', title: 'Cities'},
],
};
export const reducer = (state = initialState, action) => {
switch (action.type) {
case '@@redux/INIT': {
return {...state, title: state.routes[0].title};
}
case actionTypes.PUSH: {
// some additional logic
const newState = {...state, title: action.newState.title};
return NavigationStateUtils.push(newState, action.newState);
}
case actionTypes.POP: {
// some additional logic
const newState = {...state, title: state.routes[state.index - 1].title};
return NavigationStateUtils.pop(newState);
}
}
return state;
};
Note that I'm listening on @@redux/INIT
action. You can ommit this by manually setting title
to initialState
:
const initialState = {
index: 0,
routes: [
{key: 'cities', title: 'Cities'},
],
};
Upvotes: 1
Reputation: 1986
The first part, is in your onNavigate
that navigates to that card, you should pass a title in your state, which will automatically be pulled and used for your header component:
this.props.onNavigate({key: 'NewView', title: myuser.Username})}
The second part, I see that you are overriding renderTitleComponent
. Which means you will be responsible for passing in the title yourself (or any other data you want). Luckily, you can still read it from your scene's navigationState
(same way as is done in the default renderTitleComponent
code), by doing something like this:
renderTitleComponent={(props) => {
return <NavigationHeaderTitle>
{props.scene.navigationState.title
</NavigationHeaderTitle>;
}}
In this case, you may want to pass in the user itself in the navigationState
object, so you can grab the profile photo as well.
Upvotes: 1
Reputation: 13396
I had the same problem. As far as I know there is no best practice to do this documented anywhere. I added a custom navigation reducer that will set the title for the current scene.
function CustomReducer(lastState, action) {
switch (action.type) {
case 'updateTitle':
let newState = {...lastState, children: lastState.children.slice()};
newState.children[lastState.children.length - 1].title = action.title;
return newState;
}
return lastState;
}
Now you can do stuff like this:
componentWillMount() {
this.props.onNavigate({type: 'updateTitle', title: 'Foo'});
}
I don't like calling onNavigate for something that is clearly not navigation related, but it is extremely simple and works well so far.
I would love to see some other approaches as well.
Upvotes: 1