I am trying to call a function within useEffect, how would I mount this function within useEffect, I am not sure?
Initially useEffect is included as the following-
useEffect(() => {
CognitensorEndpoints.getDashboardList({
dispatchReducer: dispatchDashboards,
});
CognitensorEndpoints.getList({
dispatchReducer: dispatchDashboards,
});
},[]);
Then when I include function within useEffect, it returns error - 'Cannot read property 'filter' of undefined' -
useEffect(() => {
console.log('abcd');
setLoading();
CognitensorEndpoints.getDashboardList({
dispatchReducer: dispatchDashboards,
});
CognitensorEndpoints.getList({
dispatchReducer: dispatchDashboards,
});
},[]);
How do I correctly include the 'setLoading()' function within useEffect?
Here's the full app code-
import React, { useState, useEffect, useReducer } from 'react';
import { View, Text, StyleSheet, FlatList, ActivityIndicator, Keyboard, Button } from 'react-native';
import { Searchbar } from 'react-native-paper';
import { theme } from '../theme';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
import { TouchableOpacity } from 'react-native-gesture-handler';
import { apiStateReducer } from '../reducers/ApiStateReducer';
import CognitensorEndpoints from '../services/network/CognitensorEndpoints';
import DefaultView from '../components/default/DefaultView';
import DashboardListCard from '../components/DashboardListCard';
import DashboardHeader from '../components/DashboardHeader';
import DashboardGridCard from '../components/DashboardGridCard';
import {
NavigationContainer,
useFocusEffect,
} from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
const AppHeader = ({
scene,
previous,
navigation,
searchIconVisible = false,
item,
index,
onPress
}) => {
const [dashboards, dispatchDashboards] = useReducer(apiStateReducer, {
data: [],
isLoading: true,
isError: false,
});
const [gridView, setGridView] = useState(false);
const toggleGridView = () => {
setGridView(!gridView);
};
const [filtered, setFiltered] = useState([]);
const setLoading = () => {
const messages = dashboards.data.message.filter((item) => {
const title = item.dashboardTitle || item.dashboardName;
return title.toLowerCase();
});
setFiltered(messages);
console.log(filtered);
};
const dropShadowStyle = styles.dropShadow;
const toggleSearchVisibility = () => {
navigation.navigate('Search');
};
useEffect(() => {
console.log(abcd);
setLoading();
CognitensorEndpoints.getDashboardList({
dispatchReducer: dispatchDashboards,
});
CognitensorEndpoints.getList({
dispatchReducer: dispatchDashboards,
});
},[]);
return (
<>
<View style={styles.header}>
<View style={styles.headerLeftIcon}>
<TouchableOpacity onPress={navigation.pop}>
{previous ? (
<MaterialIcons
name="chevron-left"
size={24}
style={styles.visible}
/>
) : (
<MaterialIcons
name="chevron-left"
size={24}
style={styles.invisible}
/>
)}
</TouchableOpacity>
</View>
{filtered.map(item => (
<Text style={styles.headerText}>
{item.dashboardTitle}
</Text>
))}
<View style={styles.headerRightIconContainer}>
{searchIconVisible ? (
<TouchableOpacity
style={[styles.headerRightIcon, dropShadowStyle]}
onPress={toggleSearchVisibility}>
<MaterialIcons name="search" size={24} style={styles.visible} />
</TouchableOpacity>
) : (
<View style={styles.invisible} />
)}
</View>
</View>
</>
);
};
Use setfilters in useEffect. it will be called when dashboards value changed.
useEffect(() => {
console.log(dashboards);
if(dashboards.data.message) {
const messages = dashboards.data.message.filter((item) => {
const title = item.dashboardTitle || item.dashboardName;
return title.toLowerCase();
});
setFiltered(messages);
console.log(filtered);
}
},[dashboards]);
import React, { useState, useEffect, useReducer } from 'react';
import { View, Text, StyleSheet, FlatList, ActivityIndicator, Keyboard, Button } from 'react-native';
import { Searchbar } from 'react-native-paper';
import { theme } from '../theme';
import MaterialIcons from 'react-native-vector-icons/MaterialIcons';
import { TouchableOpacity } from 'react-native-gesture-handler';
import { apiStateReducer } from '../reducers/ApiStateReducer';
import CognitensorEndpoints from '../services/network/CognitensorEndpoints';
import DefaultView from '../components/default/DefaultView';
import DashboardListCard from '../components/DashboardListCard';
import DashboardHeader from '../components/DashboardHeader';
import DashboardGridCard from '../components/DashboardGridCard';
import {
NavigationContainer,
useFocusEffect,
} from '#react-navigation/native';
import { createStackNavigator } from '#react-navigation/stack';
import { createBottomTabNavigator } from '#react-navigation/bottom-tabs';
const AppHeader = ({
scene,
previous,
navigation,
searchIconVisible = false,
item,
index,
onPress
}) => {
const [dashboards, dispatchDashboards] = useReducer(apiStateReducer, {
data: [],
isLoading: true,
isError: false,
});
const [gridView, setGridView] = useState(false);
const toggleGridView = () => {
setGridView(!gridView);
};
const [filtered, setFiltered] = useState([]);
const setLoading = () => {
const messages = dashboards.data.message.filter((item) => {
const title = item.dashboardTitle || item.dashboardName;
return title.toLowerCase();
});
setFiltered(messages);
console.log(filtered);
};
const dropShadowStyle = styles.dropShadow;
const toggleSearchVisibility = () => {
navigation.navigate('Search');
};
useEffect(() => {
CognitensorEndpoints.getDashboardList({
dispatchReducer: dispatchDashboards,
});
CognitensorEndpoints.getList({
dispatchReducer: dispatchDashboards,
});
},[]);
useEffect(()={ if(dashboards.data.length > 0) { setLoading(); } },[dashboards]);
return (
<>
<View style={styles.header}>
<View style={styles.headerLeftIcon}>
<TouchableOpacity onPress={navigation.pop}>
{previous ? (
<MaterialIcons
name="chevron-left"
size={24}
style={styles.visible}
/>
) : (
<MaterialIcons
name="chevron-left"
size={24}
style={styles.invisible}
/>
)}
</TouchableOpacity>
</View>
{filtered.map(item => (
<Text style={styles.headerText}>
{item.dashboardTitle}
</Text>
))}
<View style={styles.headerRightIconContainer}>
{searchIconVisible ? (
<TouchableOpacity
style={[styles.headerRightIcon, dropShadowStyle]}
onPress={toggleSearchVisibility}>
<MaterialIcons name="search" size={24} style={styles.visible} />
</TouchableOpacity>
) : (
<View style={styles.invisible} />
)}
</View>
</View>
</>
);
};
Related
I'm making a ChatApp on ReactNative, on this part I'm trying to implement a SignOut function, but i don't understand what is wrong here.
enter image description here
The error is "undefined is not a function (near '...navigation.setOptions...')
The error is on the function:
useLayoutEffect(() => {
navigation.setOptions({
headerRight: () => (
<TouchableOpacity style={{ marginRight: 10 }} onPress={onSignOut}>
//<AntDesign name="logout" size={24} color={"#808080"} style={{marginRight:10}}/>
</TouchableOpacity>
)
});
}, [navigation]);
import React, {
useState,
useEffect,
useLayoutEffect,
useCallback,
} from "react";
import { TouchableOpacity, Text } from "react-native";
import { GiftedChat } from "react-native-gifted-chat";
import {
collection,
addDoc,
query,
onSnapshot
} from 'firebase/firestore';
import { signOut } from 'firebase/auth';
import { database } from "../config/firebase";
import { useNavigation } from "#react-navigation/native";
import {AntDesign} from "#expo/vector-icons";
import { Colors } from "react-native/Libraries/NewAppScreen";
import { auth } from "../config/firebase"
export default function Chat() {
const [messages, setMessages] = useState([]);
const navigation = useNavigation();
const onSignOut = () => {
signOut(auth).catch(error => console.log(error));
};
useLayoutEffect(() => {
navigation.setOptions({
headerRight: () => (
<TouchableOpacity style={{ marginRight: 10 }} onPress={onSignOut}>
//<AntDesign name="logout" size={24} color={"#808080"} style={{marginRight:10}}/>
</TouchableOpacity>
)
});
}, [navigation]);
useLayoutEffect(() => {
const collectionRef = collection(database, 'chats');
const q = query(collectionRef, orderBy('createAt', 'desc'));
const unsubscribe = onSnapshot(q, snapshot => {
console.log('snapshot');
setMessages(
snapshot.docs.map(doc => ({
_id: doc.id,
createdAt: doc.data().createdAt,
text: doc.data().text,
user: doc.data().user,
}))
)
});
return () => unsubscribe();
}, []);
const onSend = useCallback((messages = []) => {
setMessages(previousMessages => GiftedChat.append(previousMessages, messages));
const { _id, createdAt, text, user } = messages[0];
addDoc(collection(database, 'chats'), {
_id,
createdAt,
text,
user,
});
}, []);
return (
<GiftedChat
messages={messages}
onSend={messages => onSend(messages)}
user = {{
_id: auth?.currentUser?.email,
avatar: 'https://i.pravatar.cc/300'
}}
/>
);
}
The Navigation is on this part
This is the main part of the code, here i make the navigation into de login and signup part and the chat and home screens.
'''App.js Javascript
import React, {useState, createContext, useContext, useEffect} from "react";
import { NavigationContainer } from "#react-navigation/native";
import { createStackNavigator } from "#react-navigation/stack";
import { View, ActivityIndicator } from "react-native";
import { onAuthStateChanged } from "firebase/auth";
import Chat from "./src/screens/Chat";
import Login from "./src/screens/Login";
import Signup from "./src/screens/Signup";
import Home from "./src/screens/Home"
import { auth } from "./src/config/firebase";
const Stack = createStackNavigator();
const AuthenticatedUserContext = createContext({});
const AuthenticatedUserProvider = ({ children }) => {
const [user, setUser] = useState(null);
return (
<AuthenticatedUserContext.Provider value = {{user, setUser}}>
{children}
</AuthenticatedUserContext.Provider>
)
}
function AuthStack () {
return (
<Stack.Navigator defaultScreenOptions={Login} screenOptions={{headerShown: false}}>
<Stack.Screen name="Login" component={Login} />
<Stack.Screen name="Signup" component={Signup} />
</Stack.Navigator>
)
}
function ChatStack () {
<Stack.Navigator defaultScreenOptions={Home}>
<Stack.Screen name="Home" component={Home} />
<Stack.Screen name="Chat" component={Chat} />
</Stack.Navigator>
}
function RootNavigator () {
const {user, setUser} = useContext(AuthenticatedUserContext);
const [loading, setLoading] = useState(true);
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth,
async authenticatedUser => {
authenticatedUser ? setUser(authenticatedUser) : setUser(null);
setLoading(false);
}
);
return () => unsubscribe();
}, [user]);
if(loading) {
return (
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
<ActivityIndicator size="large" />
</View>
)
}
return (
<NavigationContainer>
{ user ? <ChatStack /> : <AuthStack />}
</NavigationContainer>
)
}
export default function App(){
return (
<AuthenticatedUserProvider>
<RootNavigator />
</AuthenticatedUserProvider>
)
}
'''
I am trying to use the values/functions from my context but every time I console.log a value that Coes from context the value is undefined.
This is my Context:
import { NativeStackNavigationProp } from '#react-navigation/native-stack';
import React, {createContext, FC, useEffect } from 'react';
import { useState } from 'react';
import {fbInit, setNewUserFireStore, subscribeUserFS } from '../services/FirebaseServices';
const initialState = {
signedIn: false,
}
export const FirebaseContext = createContext();
export const FirebaseContextProvider = ({children}) => {
const [isUserSignedIn, setIsUserSignedIn] = useState(initialState.signedIn);
useEffect(() => {
fbInit();
})
const testLog = () => {
console.log("TAG Test Log Func")
}
return (
<FirebaseContext.Provider value={{isUserSignedIn, setIsUserSignedIn}}>
{children}
</FirebaseContext.Provider>
);
}
This is where I am trying to use the values (I am trying to log the values when I press the Button)
import { useNavigation } from '#react-navigation/native';
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View } from 'react-native';
import {Button, Card, TextInput} from 'react-native-paper';
import { FirebaseContext } from '../../context/FirebaseContext';
import React, {useContext, useEffect, useState } from 'react';
const initialUserState = {
userName: 'Nicole Lopez',
password: '1001008888',
}
export default function LoginScreen() {
const [disabled, setDisabled] = useState(false);
const [userState, setUserState] = useState(initialUserState);
const { fbContext } = useContext(FirebaseContext);
const navigation = useNavigation();
const onInputChange = (field, value) => {
setUserState({
...userState,
[field]: value
})
}
useEffect(() => {
setDisabled(userState.userName.length === 0 || userState.password.length === 0);
}, [userState.userName, userState.password])
return (
<View style={styles.container}>
<Card style={styles.card}>
<TextInput
mode="outlined"
label="Förnamn & Efternman"
defaultValue={userState.userName}
onChangeText={text => onInputChange("username", text)}
right={<TextInput.Icon name="account" onPress={() => {
}}/>}
style={styles.textInput}/>
<TextInput
mode="outlined"
label="Anställningsnummer 100100xxxx"
defaultValue={userState.password}
right={<TextInput.Icon name="lock"/>}
onChangeText={text => onInputChange("password", text)}
style={styles.textInput}/>
</Card>
<View style={styles.buttonRow}>
<Button
color={disabled ? "gray" : undefined}
disabled={disabled}
mode={'contained'}
icon={'login'}
onPress={() => {
console.log("TAG isUserSignedIn: " + fbContext?.isuserSignedIn)
//fbContext?.testLog()
//console.log("TAG LOGIN BTN PRESSED")
//navigation.navigate('HomeScreen')
}}>Login</Button>
</View>
</View>
);
}
This is my App.js:
import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View } from 'react-native';
import { createNativeStackNavigator } from '#react-navigation/native-stack';
import {StackScreens} from './src/helpers/types';
import { NavigationContainer, useNavigationContainerRef } from '#react-navigation/native';
import LoginScreen from './src/screens/LoginScreen/LoginScreen';
import HomeScreen from './src/screens/HomeScreen/HomeScreen';
import {doc, getFirestore, onSnapshot, setDoc, Unsubscribe as UnsubscribeFS} from 'firebase/firestore';
import { FirebaseContextProvider, FirebaseContext } from './src/context/FirebaseContext';
import { useContext } from 'react';
//import { navigationRef } from './RootNavigation';
//const userDocument = firestore().collection("users").doc('Cstl3bA9xwwH3UwHZJhA').get();
const Stack = createNativeStackNavigator();
export default function App() {
return (
<FirebaseContextProvider>
<Content />
</FirebaseContextProvider>
);
}
export const Content = () => {
const navigationRef = useNavigationContainerRef();
const firebaseContext = useContext({FirebaseContext});
return (
<NavigationContainer ref={navigationRef}>
<Stack.Navigator initialRouteName="LoginScreen">
<Stack.Screen name="LoginScreen" component={LoginScreen} />
<Stack.Screen name="HomeScreen" component={HomeScreen} />
</Stack.Navigator>
</NavigationContainer>
);
}
Don't know what I have missed, I have installed the packages, I have tried to log different values but all seem to be undefined :/
I believe it is undefined because you're trying to destructure the context value, maybe
const { fbContext } = useContext(FirebaseContext);
should be
const fbContext = useContext(FirebaseContext);
For someone getting undefined from context, check on which level you placed your context provider. If you want to use context in a component you should wrap this component in a context provider outside of this component!
Incorrect way
const Component = () => {
const { value1, value2 } = useContext(MyContext); //here context value will be undefined
return (
<ContextProvider>
//Component content
</ContextProvider>
)
}
Correct way
const ComponentA = () => {
const { value1, value2 } = useContext(MyContext);
return(//Component A content)
}
const ComponentB = () => {
return(
<ContextProvider>
<ComponentA/>
</ContextProvider>
)
}
I'm trying to learning about chat app using expo-react native-typescript. What im doing so far is like below :
ChatRoomScreen.tsx
import React, { useState, useRef, useEffect } from 'react';
import { StyleSheet, Text, View, FlatList, SafeAreaView, ActivityIndicator } from 'react-native'
import { useRoute, useNavigation } from '#react-navigation/core'
import Message from '../components/Message'
import MessageInput from '../components/MessageInput'
// api client
import axios from 'axios';
const ChatRoomScreen = () => {
const route = useRoute()
const mounted = useRef(true);
const roomID = route.params?.id
const user = route.params?.user
const isMe = route.params?.isMe
const [message, setMessage] = useState();
//AxiosRequest
//get chats
const fetchMessages = async () =>{
axios.get('https://mylaravelAPI.com/api/get/'+roomID)
.then(function (response) {
// handle success
const result = response.data.message.reverse();
{setMessage(result)}
})
}
useEffect(() => {
fetchMessages()
},[])
return (
<SafeAreaView style={styles.page}>
<FlatList
data={message}
//Send params to Message
renderItem={({item}) => <Message message={item} roomID={roomID}/> }
inverted
/>
<MessageInput
//Send params to MessageInput
id={route.params?.id}
receiveID={route.params?.user}
userID={route.params?.isMe}
/>
</SafeAreaView>
)
}
export default ChatRoomScreen
Message.tsx
import React from 'react'
import { StyleSheet, Text, View } from 'react-native'
const blue = '#3777f0'
const grey = 'lightgrey'
const myID = '1'
const Message = ({ message, roomID }) => {
const isMe = message.user.id == myID
const roomId = roomID
return (
<View style={[
styles.container, isMe ? styles.rightContainer : styles.leftContainer]}
>
<Text style={{ color: isMe ? 'black' : 'white' }}>{message.content}</Text>
</View>
)
}
export default Message
MessageInput.tsx
import React, { useState, useEffect } from 'react'
import { StyleSheet, Text, View, TextInput, Pressable } from 'react-native'
import { SimpleLineIcons, Feather, MaterialCommunityIcons, AntDesign, Ionicons } from '#expo/vector-icons'
import MessageComponent from "../Message";
// api client
import axios from 'axios';
const MessageInput = ({id, receiveID, userID}) => {
const [message, setMessage] = useState()
const chatroom = id
const senderUserID = userID.id
const receiveUserID = receiveID.id
//Action
//save message
const saveMessage = () => {
axios({
method: 'post',
url: 'https://mylaravelAPI.com/api/post',
headers: {
'content-type': 'application/json',
},
data: JSON.stringify({
"content": message,
"userID": senderUserID,
"replyToID": receiveUserID
})
});
setMessage('')
}
//update message
const updateMessage = () => {
console.log('updateMessage')
}
//OnPress
const onPress2 = () => {
if (chatroom === null) {
{saveMessage()}
}else{
{updateMessage()}
}
}
const onPress = () => {
// console.log(message)
}
return (
<View style={styles.root}>
<View style={styles.inputContainer}>
<SimpleLineIcons name='emotsmile' size={24} color='#595959' style={styles.icon}/>
<TextInput
style={styles.input}
value={message}
onChangeText={setMessage}
placeholder="Signal message..."
/>
<Feather name='camera' size={24} color='#595959' style={styles.icon}/>
<MaterialCommunityIcons name='microphone-outline' size={24} color='#595959' style={styles.icon}/>
</View>
{/* <Pressable onPress={onPress} style={styles.buttonContainer}>
{message ? <Ionicons name="send" size={18} color="white" /> : <AntDesign name='plus' size={24} color='white' />}
</Pressable> */}
<View onPress={onPress} style={styles.buttonContainer}>
{message ?
<Pressable
onPress={onPress2}>
<Ionicons name="send" size={18} color="white" />
</Pressable> :
<Pressable
onPress={onPress}>
<AntDesign name='plus' size={24} color='white' />
</Pressable>
}
</View>
</View>
)
}
export default MessageInput
Everything is working except the message not update or shows ini realtime. It's will show only when i go back to Welcome screen and open the chat/room again... please help me.. thanks
I have created Table component. In this component i have created two buttons. one for download and second is share. both have onPress method. I have imported this Table component in the dashboard component. but I am unable to use both methods individually in my dashboard component.please suggest any solution for this problem.
Table Component:
import React, { StrictMode, useEffect, useState } from "react";
import { Text, View, ActivityIndicator } from "react-native";
import Size from "../../constants/Sizes";
import Strings from "../../constants/Strings";
import { Table, TableWrapper, Row, Rows } from "react-native-table-component";
import Color from "../../constants/Colors";
import Icon from "../../styles/Icons";
import api from "../../services/api";
import ListModel from "../ListModal";
import { TableTwoStyle as tableStyle } from "../../styles";
import { heightToDp } from "../../constants/Utils";
const TableTwo = (props) => {
const [files, setFiles] = useState([]);
const [modalState, setModalState] = useState(false);
useEffect(() => {
const fileData = api.getFileOptions();
setFiles(fileData);
}, []);
const { data } = props;
const handleOptions = (title) => {
console.log("title", title);
props.onPress(title);
// this.closeModal();
};
const openModal = () => {
setModalState(true);
};
const closeModal = () => {
setModalState(false);
};
return (
<StrictMode>
{data !== undefined ? (
<View style={tableStyle.mainContainer}>
<View style={tableStyle.HeadingSection}>
<View style={tableStyle.LabelContainer}>
<View style={tableStyle.leftSection}>
<Text style={tableStyle.labelText}>{Strings.tableTitle}</Text>
</View>
<View style={tableStyle.rightSection}>
<Icon.MaterialIcons
name="file-download"
color={Color.gray}
style={tableStyle.exportButton}
size={heightToDp(Size.per_4_5)}
onPress={openModal}
/>
</View>
<View style={tableStyle.rightSection}>
<Icon.MaterialIcons
name="share"
color={Color.info}
style={tableStyle.exportButton}
size={heightToDp(Size.per_4)}
onPress={openModal}
/>
</View>
</View>
<View style={tableStyle.divider} />
</View>
<View style={tableStyle.TableSection}>
{data.headers && data.headers.length > 0 ? (
<Table
borderStyle={{
borderWidth: Size.px_1,
borderColor: Color.dividerColor,
}}
>
<Row
data={data.headers}
flexArr={[Size.num_1]}
style={tableStyle.head}
textStyle={tableStyle.headerText}
/>
<TableWrapper style={tableStyle.wrapper}>
<Rows
data={data.data}
flexArr={[Size.num_1]}
style={tableStyle.row}
textStyle={tableStyle.text}
/>
</TableWrapper>
</Table>
) : (
<ActivityIndicator color={Color.loaderColor} size={Strings.lg} />
)}
</View>
<ListModel
modalState={modalState}
close={closeModal}
onPress={handleOptions}
data={files}
/>
</View>
) : null}
</StrictMode>
);
};
export default TableTwo;
Dashboard Component:
import React, { StrictMode, Component } from "react";
import { View, ScrollView } from "react-native";
import { GraphCardList as GraphList } from "../components";
import { InfoCardList as InfoList } from "../components";
import { TableTwo as Table } from "../components";
import Loader from "../components/Loader";
import Store from "../database/Storage";
import OptionsCard from "../components/Option";
import { Card as CardUI } from "../components";
import { dashboardStyle as dashboardUI } from "../styles";
import Api from "../services/api";
import inputValidation from "../helper/Validation";
import TableExport from "../exports/TableExport";
import Permission from "../services/AppPermission";
export default class DashboardScreen extends Component {
constructor(props) {
super(props);
this.state = {
tableList: [],
};
this.downloadData = this.downloadData.bind(this);
}
componentDidMount() {
}
componentWillUnmount() {
}
downloadData(title) {
...
}
shareData(){
....
}
render() {
const {
loader2,
infoList,
chartList,
tableList,
userList,
loader,
pauseState,
} = this.state;
//console.log("users",infoList);
if (loader) {
return (
<View style={dashboardUI.mainContainer}>
<Loader />
</View>
);
}
return (
<StrictMode>
<CardUI style={dashboardUI.Cards}>
<Table data={tableList} onPress={this.downloadData} />
</CardUI>
)}
</StrictMode>
);
}
}
If your'e passing same prop for two different buttons that means that the two buttons will execute the same method , but if you want to pass different methods for each button just pass a different props.
For example component B:
<View>
<Button title="Download" onPress={props.download}/>
<Button title="Share" onPress={props.share}/>
</View>
Component A:
<B download={this.downloadData} share={this.shareData}/>
Please try below code:
**In Dashboard Component:**
downloadData() {
}
`return (<Table data={tableList} handleDownloadData={this.downloadData} />);`
**In Table Component:**
const download = (data) => {
props.handleDownloadData(data);
};
const share = (data) => {
props.handleDownloadData(data);
};`
`return (<div><Button onClick={download}> Download</Button><Button onClick={share}> Share</Button></div>);
`
I have an issue with react-navigation in passing the props to another screen,
I need to pass some props to Detail screen when the user presses one of the List Places I need to push screen with some details about the place like a Name of place and Image of place,
Errors :
this is my Code
Reducer
import { ADD_PLACE, DELETE_PLACE } from "../actions/actionTypes";
const initialState = {
places: []
};
import placeImage from "../../assets/img.jpg";
const reducer = (state = initialState, action) => {
switch (action.type) {
case ADD_PLACE:
return {
...state,
places: state.places.concat({
key: Math.random(),
name: action.placeName,
// image: placeImage,
image: {
uri:
"https://images.unsplash.com/photo-1530009078773-9bf8a2f270c6?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=750&q=80"
}
})
};
case DELETE_PLACE:
return {
...state,
places: state.places.filter(place => {
return place.key !== state.selectedPlace.key;
})
};
default:
return state;
}
};
export default reducer;
Place List Component
import React from "react";
import { FlatList, StyleSheet, ScrollView } from "react-native";
import ListItem from "../ListItem/ListItem";
const PlaceList = props => {
return (
<FlatList
style={styles.listContainer}
data={props.places}
renderItem={info => (
<ListItem
placeName={info.item.name}
placeImage={info.item.image}
onItemPressed={() => props.onItemSelected(info.item.key)}
/>
)}
keyExtractor={index => String(index)}
/>
);
};
export default PlaceList;
Find Place Screen
import React, { Component } from "react";
import { View, Text } from "react-native";
import { connect } from "react-redux";
import { StackActions } from "react-navigation";
import PlaceList from "../../Components/PlaceList/PlaceList";
class FindPlaceScreen extends Component {
constructor() {
super();
}
itemSelectedHandler = key => {
const selPlace = this.props.places.find(place => {
return place.key === key;
});
this.props.navigation.push("PlaceDetail", {
selectedPlace: selPlace,
name: selPlace.name,
image: selPlace.image
});
};
render() {
return (
<View>
<PlaceList
places={this.props.places}
onItemSelected={this.itemSelectedHandler}
/>
</View>
);
}
}
const mapStateToProps = state => {
return {
places: state.places.places
};
};
export default connect(mapStateToProps)(FindPlaceScreen);
Place Details Screen
import React, { Component } from "react";
import { View, Text, Image, TouchableOpacity, StyleSheet } from "react-native";
import Icon from "react-native-vector-icons/Ionicons";
class PlaceDetail extends Component {
constructor(props) {
super(props);
}
render() {
return (
<View style={styles.modalContainer}>
<View>
<Image
source={this.props.navigation.state.params.image}
style={styles.placeImage}
/>
<Text style={styles.placeName}>
{this.props.navigation.state.params.namePlace}
</Text>
</View>
<View>
<TouchableOpacity onPress={props.onItemDeleted}>
<View style={styles.deleteButton}>
<Icon size={30} name="ios-trash" color="red" />
</View>
</TouchableOpacity>
<TouchableOpacity onPress={props.onModalClosed}>
<View style={styles.deleteButton}>
<Icon size={30} name="ios-close" color="red" />
</View>
</TouchableOpacity>
</View>
</View>
);
}
}
export default PlaceDetail;
You need to use react-native-navigation v2 for the find place screen
itemSelectedHandler = key => {
const selPlace = this.props.places.find(place => {
return place.key === key;
});
Navigation.push(this.props.componentId, {
component: {
name: 'PlaceDetail',
options: {
topBar: {
title: {
text: selPlace.name
}
}
},
passProps: {
selectedPlace: selPlace
}
}
});
};
make sure you import { Navigation } from "react-native-navigation";
Your PlaceDetail has some error
<TouchableOpacity onPress={props.onItemDeleted}>
<TouchableOpacity onPress={props.onModalClosed}>
Change props to this.props
<TouchableOpacity onPress={this.props.onItemDeleted}>
<TouchableOpacity onPress={this.props.onModalClosed}>
But I don't see onItemDeleted and onModalClosed anywhere, don't forget to pass those to PlaceDetail via props as well :)