I am new to react native and I am trying to access a context from a bottomtab navigator where the context was created in the stack navigator stackCreate and the tab navigator is nested in stackCreate, but when i try to add a new object to the context in addTab i get: undefined is not an object (evaluating 'tabs.pop().name')
, but when i call console.log(tabs.pop().name.replace("Step ", ""));
it works, so I am confused why this is happening.
navigators;
const Stack = createStackNavigator();
const StackCreate = createStackNavigator();
const StepTabs = createBottomTabNavigator();
const StepStack = () => {
return (
<tabContext.Consumer>
{({tabs}) => (
<StepTabs.Navigator
screenOptions={{
tabBarHideOnKeyboard: true
}}
>
{
tabs.map((tab) => <StepTabs.Screen key={tab.name} name={tab.name} stepTitle={tab.stepTitle} component={tab.component}
options={{
tabBarLabel: `${tab.stepTitle}`,
}}
/> )
}
</StepTabs.Navigator>
)}
</tabContext.Consumer>
)
}
const CreateStack = () => {
const [tabs, setTabs] = useState([
{
name: 'Step 1',
component: CreateStep,
stepTitle: 'Step 1',
}
]);
const [ingredientsList, setIngredientsList] = useState([]);
return (
<ingredientContext.Provider value={{ingredientsList, setIngredientsList}}>
<tabContext.Provider value={{tabs, setTabs}}>
<StackCreate.Navigator>
<StackCreate.Screen name="Create" component={Create}/>
<StackCreate.Screen name="IngredientStep" component={IngredientStep}/>
<StackCreate.Screen name="MyModal" component={ModalScreen}
screenOptions={{ presentation: 'modal' }}/>
<StackCreate.Screen name="StepStack" component={StepStack}/>
</StackCreate.Navigator>
</tabContext.Provider>
</ingredientContext.Provider>
)
}
const RootStack =() => {
return (
<userContext.Consumer>
{({UserId}) => (
<NavigationContainer>
<Stack.Navigator
screenOptions={{
headerStyle: {
backgroundColor: "transparent",
},
headerShown: false,
headerTintColor: Colors.tertiary,
headerTransparent: true,
headerTitle: '',
headerLeftContainerStyle: {
paddingLeft: 20,
}
}}
>
{UserId ? (
<Stack.Group>
<Stack.Screen name="Home" component={Home}/>
<Stack.Screen name="Recipes" component={Recipes} />
<Stack.Screen name="CreateStack" component={CreateStack} />
</Stack.Group>
) : (
<Stack.Group>
<Stack.Screen name="Login" component={Login}/>
<Stack.Screen name="Register" component={Register}/>
</Stack.Group>
)}
</Stack.Navigator>
</NavigationContainer>
)
}
</userContext.Consumer>
);
}
export default RootStack;
createStep
const CreateStep = ({navigation, route}) => {
const {tabs, setTabs } = useContext(tabContext);
const removeTab = (route) => {
setTabs(tabs => tabs.filter(tab => {if(tab.stepTitle != route.stepTitle){if(parseInt(tab.stepTitle.replace("Step ", "")) > parseInt(route.stepTitle.replace("Step ", ""))){tab.stepTitle = 'Step ' (parseInt(tab.stepTitle.replace("Step ", "")) - 1);} return tab;}}));
}
const addTab = () => {
//console.log(tabs.pop().name.replace("Step ", ""));
setTabs(tabs => [...tabs,
{
name: 'Step ' (parseInt(tabs.pop().name.replace("Step ", "")) 1),
component: CreateStep,
stepTitle: 'Step ' (parseInt(tabs.pop().stepTitle.replace("Step ", "")) 1),
}
])
}
const finishRecipe = () => {
navigation.navigate("Recipes");
}
return (
<StyledContainer>
<InnerContainer>
<StyledFormArea>
<StyledTextInputLarge multiline={true} />
</StyledFormArea>
<View style={{
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
height: 10,
width: '100%',
}}>
{(tabs.length < 10) ? (<Button title="Add Step" onPress={addTab}/>) : null}
{(route.name != 'Step 1') ? (<Button title="Remove Step" onPress={() => removeTab(route)}/>) : null }
<Button title="Finish Recipe" onPress={finishRecipe}/>
</View>
</InnerContainer>
</StyledContainer>
)
}
export default CreateStep;
CodePudding user response:
First, when you call tabs.pop()
, it remove the last value from tabs array and return this value.
I guess you're calling tabs.pop()
twice:
- The first time you call, it work fine because
tabs
is not empty. - But when you call the second time, tabs is empty at this time and
tabs.pop()
return undefined. Of course,undefined.name
make a error.
Example:
const plants = ['broccoli'];
console.log(plants.pop());//"broccoli"
console.log(plants.pop());//undefined
You can read: array.pop() for more infomation.
I suggest that I can assign returned value in tabs for a variable like tab:
const tab = tabs.pop()
After that, I use tab instead of tabs.pop()