How to dispatch state in class component using React-redux? - reactjs

I'm trying to get my head around Redux.
Here's the MainMap.js:
import React from 'react';
import {
TouchableWithoutFeedback,
StyleSheet,
Keyboard,
PermissionsAndroid,
Platform,
View,
Button,
FlatList,
Dimensions,
TouchableOpacity,
Text
} from 'react-native';
import * as placeAction from '../../store/actions/place/place';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
class MainMap extends React.Component{
constructor(props){
super(props);
this.state={
//....
destinationName: [],
destinationAddress: [],
//...
};
//......
this.addPlaceHandle = this.addPlaceHandle.bind(this)
};
//....
// Dispatch a place
addPlaceHandle(name, address){
this.props.addingPlace(name, address);
}
render(){
const {container, map, listOfSearchBars, buttonView, button, next} = styles
const { destinationCoords, userLatitude, userLongitude, initial_UserLatitude, initial_UserLongitude } = this.state;
//....
return(
<TouchableWithoutFeedback onPress={this.hideKeyboard} >
<View style={container} >
<View style={buttonView}>
<TouchableOpacity style={button} onPress={() => {
this.addPlaceHandle(this.state.destinationName, this.state.destinationAddress);
}}>
<Text style={next}>Next</Text>
</TouchableOpacity>
</View>
</View>
</View>
</TouchableWithoutFeedback>
)
}
componentWillUnmount(){
Geolocation.clearWatch(this.watch_location_id);
}
}
//}
const styles = StyleSheet.create({
container:{
flex: 1
},
map:{
...StyleSheet.absoluteFillObject
},
listOfSearchBars:{
...
},
buttonView:{
...
},
button:{
...
},
next: {
...
}
});
const mapDispatchToProps = (dispatch) => ({
addingPlace: (_name, _address) => dispatch(placeAction.addPlace(_name, _address))
})
export default connect(null, mapDispatchToProps)(MainMap)
Basically, the MainMap.js is like Google Map. You search a location, choose it from the suggestions, and it'll show the direction for you.
After loads of async/await functions and this.setState(), the name and the address from the location we choose will be added to the this.state.destinationName and this.state.destinationAddress, respectively.
I've successfully done that. Now I want to dispatch that data which is the name & address to the store
place.js in actions:
export const ADD_PLACE = 'ADD_PLACE';
export const addPlace = (name, address) => {
return {
type: ADD_PLACE,
placeData: {
name: name,
address: address
}
};
};
Here's the place.js in reducers:
import { ADD_PLACE } from '../../actions/place/place';
import Place from '../../../src/models/place';
const initialState = {
places: []
};
export default (state = initialState, action) => {
switch(action.type){
case ADD_PLACE:
const newPlace = new Place(
action.placeData.name,
action.placeData.address
);
return {
places: state.places.concat(newPlace)
};
default: return state;
}
}
But I get this error when I click the button:
Any answers and recommended resources are deeply appreciated !

The problem is I did import the Place incorrectly
It has to be:
import {Place} from ''
Thanks #hussain for helping me

Related

passing textinput value from one screen into another using mapDispatchToProps

I want to pass value of a textinput from one screen to another using mapDispatchToProps. I am roughly a newbie in the redux world and I am a bit confused. kindly make corrections to my code below. I have tried using the example implemented on the documentation, however, I do not fully understand mapDispatchToProps.
PS I tried to keep the code as simple as possible for better understanding
Screen1
import React, { Component, Fragment } from 'react';
import {
View,
Text,
StyleSheet,
} from 'react-native';
import { connect } from 'react-redux';
class Screen1 extends Component {
static navigationOptions = {
header: null,
}
constructor(props) {
super(props);
this.state = {
total: 1,
};
this.onChangeText = this.onChangeText.bind(this);
}
onChangeText(number) {
const total = parseInt(number);
if (number.length === 0) {
this.setState({ total: '' });
} else {
this.setState({ total });
}
}
render() {
return (
<SafeAreaView style={styles.AndroidSafeArea}>
<View style={styles.wrapper}>
<ScrollView
showsVerticalScrollIndicator={false}
contentContainerStyle={styles.scrollableList}
>
<InputField
children={"Receiver's phone no."}
iconType={'ios-call'}
placeholder={"number"}
keyboardType={'phone-pad'}
maxLength={11}
/>
<InputField
children={"Receiver's gifts"}
iconType={'ios-basket'}
placeholder={'Gifts'}
keyboardType={'phone-pad'}
maxLength={2}
onChangeText={this.onChangeText}
value={this.state.total.toString()}
/>
</ScrollView>
</View>
</SafeAreaView>
);
}
}
function mapDispatchToProps(dispatch) {
return {
total: () => {
dispatch(this.onChangeText());
}
}
}
export default connect(mapDispatchToProps) (Screen1);
Screen2
import React, { Component, Fragment } from 'react';
import {
View,
Text,
StyleSheet,
} from 'react-native';
import { connect } from 'react-redux';
class Screen2 extends Component {
static navigationOptions = {
header: null,
}
constructor(props) {
super(props);
this.state = {
};
}
render() {
return (
<SafeAreaView style={styles.AndroidSafeArea}>
<View style={styles.wrapper}>
<ScrollView
showsVerticalScrollIndicator={false}
contentContainerStyle={styles.scrollableList}
>
<Text>{this.props.onChangeText}</Text>
</ScrollView>
</View>
</SafeAreaView>
);
}
}
function mapStateToProps(state) {
return {
total: state.onChangeText
}
}
}
export default connect(mapStateToProps) (Screen2);
Reducer.js
import { TOTAL_GIFTS } from '../actions/types';
const initialState = {
total: ''
};
const Reducer = (state = initialState, action) => {
switch (action.type) {
case TOTAL_GIFTS:
return {
...state,
total: action.total
};
default:
return state;
}
};
export default Reducer;
Im leaving the none redux related parts of your code out.
Screen1
class Screen1 extends React.component{
handleChange(number){
this.props.announceChange(number)
}
}
//mapping dispatch to props
function mapDispatchToProps(dispatch){
announceChange(number)
}
//action creator
function announceChange(number){
return {type:'SOME_CONSTANT',payload:number}
}
export default connect(null,mapStateToProps)(Screen1)
Reducer:
export default function reducer(state={},action){
switch(action.type){
case 'SOME_CONSTANT':
return {...state,number:action.payload}
default :
return state;
}
}
screen2:
class Screen2 extends React.component{
render(){
const {number} = this.props
return(
<span>{number}</span>
)
}
}
function mapStateToProps(state){
return {
number : state.reducername
}
}
export default connect(mapStateToProps)(Screen2);
the above code is a minimal sample of the way you can use redux. if you dont have any ideas how to setup your store,reducer and other redux stuff reading this wont take more than 10 mints.
mapDispatchToProps: are functions/actions to update store(redux)
mapStateToProps : to get data from store(redux)
on first screen you will disptach action to update email using mapDispatchToProps
on second you will get email from mapStateToProps
I have created a sample code for you (CHECK IN ANDROI/IOS)
Please check https://snack.expo.io/#mehran.khan/reduxtest
APP PREVIEW

React-Redux | Productlist | Add/Remove w/ BindActionCreator

I'm trying to create an product list in React where I can add and remove products.
I started to do some research on how I could do this using the redux framework/platform and react native
I already have an function productList container, product component and cartList, cartProduct component.
My problems are:
Products: I can only add products and not remove
Cart: Vice versa + the cart does not get updated on the status of the cart items.
I've added bindActionCreator but don't know how to apply it to my productList yet.
What do I expect to happen?
I'm trying to add and remove products from the react store in the same container/component.
How can I do this? Is my approach correct or am I completely wrong ?
A thank you in advance.
ProductActionCreators
export const ADD_TO_CART = 'ADD_TO_CART'
export const REMOVE_FROM_CART = 'REMOVE_FROM_CART'
export function addItemToCart(row) {
return {
type:'ADD_TO_CART',
payload: row, qty
}
}
export function removeTodo(row) {
return {
type:'REMOVE_FROM_CART' ,
payload: row, qty
}
}
ProductList(simplified)
import React from 'react';
import { Component } from 'react';
import {
View,
StyleSheet,
Text
} from 'react-native';
import Products from '../components/Products';
import { bindActionCreators} from 'redux';
import { connect } from 'react-redux';
import * as ProductActionCreators from '../actions/ProductActionCreators'
export class ProductList extends React.Component {
static navigationOptions = {
header: null,
};
constructor(props) {
super(props);
const { rows } = this.props.navigation.state.params;
const arrays = Object.values( {rows});
this.state = {
arrays,
filteredProducts: arrays,
};
const { dispatch } = props
this.boundActionCreators = bindActionCreators(ProductActionCreators, dispatch)
console.log(this.boundActionCreators)
}
render() {
return (
<View style={styles.container} >
<Text style={styles.title} >
{this.state.arrays[0].name}
</Text>
<Products products={this.state.arrays[0].data} onPress=
//Trying to change this to multiple actions
{this.props.addItemToCart}/>
</View>
)
}
}
const qty = 0;
const mapDispatchToProps = (dispatch) =>{
//need to add BindActionCreator
return{
addItemToCart:(row) => dispatch({
type:'ADD_TO_CART', payload: row, qty
}),
removeItem:(product) => dispatch ({
type:'REMOVE_FROM_CART' , payload: product, qty
})
}
}
export default connect(null, mapDispatchToProps) (ProductList);
Product(simplified)
import React, { Component } from "react";
import {
View,
Text,
TouchableOpacity,
TextInput,
FlatList,
} from "react-native";
import Icon from "react-native-vector-icons/Ionicons";
class Products extends Component {
constructor(props) {
super(props);
const { products } = this.props;
this.state = {
products,
filteredProducts: products,
};
}
renderProducts = (products) => {
return (
<View key={products.index}>
<View>
<Icon name={products.item.icon} color="#DD016B" size={25} />
</View>
<View>
<Text style={styles.name}>
{products.item.name}
</Text>
<Text>
€ {products.item.price}
</Text>
</View>
<View style={styles.buttonContainer}>
<TouchableOpacity onPress={() => this.props.onPress(products.item)} >
<Icon name="ios-add" color="white" size={25} />
</TouchableOpacity>
<TouchableOpacity onPress={() => this.props.onPress(products.item)} >
<Icon name="ios-remove" color="white" size={25} />
</TouchableOpacity>
</View>
</View>
)
}
render() {
return (
<View>
<FlatList
style={styles.listContainer}
data={this.state.filteredProducts}
renderItem={this.renderProducts}
keyExtractor={(item, index) => index.toString()}
/>
</View>
);
}
}
export default Products;
reducers/cartItems
const cartItems = (state = [], action) => {
switch (action.type)
{
case 'ADD_TO_CART':
if (state.some(cartItem => cartItem.id === action.payload.id)) {
// increase qty if item already exists in cart
return state.map(cartItem => (
cartItem.id === action.payload.id ? { ...cartItem, qty: cartItem.qty + 1 } : cartItem
));
}
return [...state, { ...action.payload, qty: 1 }];
// else add the new item to cart
case 'REMOVE_FROM_CART':
return state
.map(cartItem => (cartItem.id === action.payload.id ? { ...cartItem, qty: cartItem.qty - 1 } : cartItem))
.filter(cartItem => cartItem.qty > 0);
}
return state
}
export default cartItems
store/Index
import {createStore} from 'redux';
import cartItems from '../reducers/carItems';
export default store = createStore(cartItems)
App structure (simplified)
Main folder
↳
Containers(folder)
↳
ProductsList.js
CartList.js
Components(folder)
↳
Product.js
cartProduct.js
Reducers(folder)
↳
carItems.js
Actions(folder)
↳
ProductActionCreators.js
Navigation(folder)
↳
AppNavigator,js
MainTabNavigator.js
Assets(folder for images etc.)
Store(folder)
↳
index.js
App.JS
Data.JS (using static JSON file for this development phase)
You have two different actions, addItemToCart, removeItem which you define in mapDispatchToProps. Now that you specify a mapDispatchToProps argument to connect, the dispatch method is not available as a prop to the connected component, instead the method returns by mapDispatchToProps are only available
Second, you don't need to use bindActionCreators and definitely not in the component. MapDispatchToProps can simply be an object and connect will use dispatch internally.
Third, you need to pass the add and remove actions both to the child component.
Fourth you can pass multiple actions on to Product component simply as prop
Your code would look like
ProductActionCreators.js
export const ADD_TO_CART = 'ADD_TO_CART'
export const REMOVE_FROM_CART = 'REMOVE_FROM_CART'
export function addItemToCart(row) {
return {
type:'ADD_TO_CART',
payload: row
}
}
export function removeItem(item) {
return {
type:'REMOVE_FROM_CART' ,
payload: item
}
}
ProductList
import React from 'react';
import { Component } from 'react';
import {
View,
StyleSheet,
Text
} from 'react-native';
import Products from '../components/Products';
import { connect } from 'react-redux';
import { addItemToCart, removeItem } from '../actions/ProductActionCreators';
export class ProductList extends React.Component {
static navigationOptions = {
header: null,
};
constructor(props) {
super(props);
const { rows } = this.props.navigation.state.params;
const arrays = Object.values( {rows});
this.state = {
arrays,
filteredProducts: arrays,
};
}
render() {
return (
<View style={styles.container} >
<Text style={styles.title} >
{this.state.arrays[0].name}
</Text>
<Products products={this.state.arrays[0].data} addItemToCart={this.props.addItemToCart} removeItem={this.props.removeItem}/>
</View>
)
}
}
const mapDispatchToProps = {
addItemToCart,
removeItem
}
export default connect(null, mapDispatchToProps) (ProductList);
Product
import React, { Component } from "react";
import {
View,
Text,
TouchableOpacity,
TextInput,
FlatList,
} from "react-native";
import Icon from "react-native-vector-icons/Ionicons";
class Products extends Component {
constructor(props) {
super(props);
const { products } = this.props;
this.state = {
products,
filteredProducts: products,
};
}
renderProducts = (products) => {
return (
<View key={products.index}>
<View>
<Icon name={products.item.icon} color="#DD016B" size={25} />
</View>
<View>
<Text style={styles.name}>
{products.item.name}
</Text>
<Text>
€ {products.item.price}
</Text>
</View>
<View style={styles.buttonContainer}>
<TouchableOpacity onPress={() => this.props.addItemToCart(products.item)} >
<Icon name="ios-add" color="white" size={25} />
</TouchableOpacity>
<TouchableOpacity onPress={() => this.props.removeItem(products.item)} >
<Icon name="ios-remove" color="white" size={25} />
</TouchableOpacity>
</View>
</View>
)
}
render() {
return (
<View>
<FlatList
style={styles.listContainer}
data={this.state.filteredProducts}
renderItem={this.renderProducts}
keyExtractor={(item, index) => index.toString()}
/>
</View>
);
}
}
export default Products;
Code looks alright for most part.
The react-redux connect part in ProductList looks off. qty is always 0. It should be 1.
Also, mapStateToProps should be present to get the products from the cart.
In your ProductList, I'd approach the action binding like so:
const mapDispatchToProps = (dispatch) =>{
return bindActionCreators({
addItemToCart: (row, qty) => dispatch({
type:'ADD_TO_CART', payload: {row, qty}
}),
removeItem: (product, qty) => dispatch({
type:'REMOVE_FROM_CART' , payload: {product, qty}
})
})
}
export default connect(null, mapDispatchToProps)(ProductList);
Remove the action binding from your component's constructor as that's unnecessary.
You may want to split the code out into a Container/Component/ HOC approach, as I find it makes code far easier to read. As you've defined your actions in separate file, I'd also import these rather than redeclaring them.
If you follow this advice, you'd end up with the following:
container.js
import { bindActionCreators } from 'redux';
import ProductList from './product-list';
// Actions
import { addItemToCart, removeItem } from './actions';
function mapStateToProps(state) {
return {}
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({
addItemToCart,
removeItem,
})
}
export default connect(mapStateToProps, mapDispatchToProps)(ProductList);
product-list.js
import React from 'react';
import { View, Text } from 'react-native';
import Products from '../components/Products';
export class ProductList extends React.Component {
static navigationOptions = {
header: null,
};
constructor(props) {
super(props);
const { rows } = this.props.navigation.state.params;
const arrays = Object.values( {rows});
this.state = {
arrays,
filteredProducts: arrays,
};
this.handleProductPress = this.handleProductPress.bind(this);
}
handleProductPress(e) {
e.preventDefault();
// This is pseudo code...
this.props.addItemToCart(e.target.value, 1);
return;
}
render() {
return (
<View style={styles.container} >
<Text style={styles.title} >
{this.state.arrays[0].name}
</Text>
<Products products={this.state.arrays[0].data} onPress={this.handleProductPress} />
</View>
)
}
}
export default ProductList;
Have a play with that and see how you get on.

React native, delay api call?

I have a method called: onChangeText
It means every time I type, it will search the remote api.
How do I delay the remote api call? i.e. let user types certain things, then connect the api, rather than connect every key stroke.
onChangeText(title) {
console.log('-- chg text --');
console.log(title);
this.props.searchApi(title);
}
The component:
import React, { Component } from 'react';
import { SearchBar, Divider } from 'react-native-elements';
import { View, ScrollView, Text, StyleSheet, Image} from 'react-native';
import { connect } from 'react-redux';
// action creator
import { searchApi } from './reducer';
class SearchContainer extends Component {
constructor(props) {
super(props);
}
onChangeText(title) {
console.log('-- chg text --');
console.log(title);
this.props.searchApi(title);
}
onClearText(e) {
console.log('-- clear text --');
console.log(e);
}
render() {
const { } = this.props;
const containerStyle = {
display: 'flex',
justifyContent: 'center',
alignItems: 'center'
}
const searchStyle = {
width: 300,
height: 45
};
return (
<View
style={containerStyle}
>
<Image
source={require('../../asset/img/logo.png')}
style={{
height: 150,
width: 150
}}
/>
<SearchBar
cancelButtonTitle="Cancel"
placeholder='Search'
containerStyle={searchStyle}
onChangeText={this.onChangeText.bind(this)}
onClearText={this.onClearText.bind(this)}
/>
</View>
);
}
}
const mapStateToProps = state => {
return {
};
};
const mapDispatchToProps = dispatch => {
return {
searchApi: () => dispatch(searchApi())
}
};
export default connect(mapStateToProps, mapDispatchToProps)(SearchContainer);
Use lodash debounce. It is used for this exact use case
Sample React example. Should be able to port to native the same way
import React, {Component} from 'react'
import { debounce } from 'lodash'
class TableSearch extends Component {
//********************************************/
constructor(props){
super(props)
this.state = {
value: props.value
}
this.changeSearch = debounce(this.props.changeSearch, 250)
}
//********************************************/
handleChange = (e) => {
const val = e.target.value
this.setState({ value: val }, () => {
this.changeSearch(val)
})
}
//********************************************/
render() {
return (
<input
onChange = {this.handleChange}
value = {this.props.value}
/>
)
}
//********************************************/
}

React Native wont render next array items at setState

Hello I am trying to make a step wizard component but I have the following issue. I have the following file:
import React from 'react';
import { View } from 'react-native';
import WizardStep from './WizardStep'
export default class Wizard extends React.Component {
constructor(props){
super(props);
this.state = {
questions: this.props.questions,
answers: this.props.answers,
totalSteps: this.props.questions.length,
currentStep: 0,
results: []
}
}
updateStep = answer => {
newResults = this.state.results
newResults[this.state.currentStep - 1] = answer
this.setState({
results: newResults,
currentStep: this.state.currentStep + 1
}, () => {
if (this.state.currentStep == this.state.totalSteps) {
this.props.finish();
}
})
}
renderStep = () => {
if (this.state.currentStep < this.state.totalSteps) {
return (
<View>
<WizardStep
question={this.state.questions[this.state.currentStep]}
answers={this.state.answers[this.state.currentStep]}
step={this.state.currentStep}
totalSteps={this.state.totalSteps}
updateStep={this.updateStep}
/>
</View>
);
} else {
return null;
}
}
render(){
return(
<View>
{this.renderStep()}
</View>
)
}
}
questions is an array of strings and answers is an array of arrays of strings.
Anyway the first screen shows up just fine. But when I call the updateStep function the currentStep updates but it doesn't show the 2nd item from questions/answers array. Any ideas? Thank you in advance!
Adding the other components for the wizard:
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { Button } from "react-native-elements";
import { Constants } from 'expo';
import WizardStepButton from './WizardStepButton';
export default class WizardStep extends React.Component {
constructor(props){
super(props);
this.state ={
question: this.props.question,
answers: this.props.answers,
totalSteps: this.props.totalSteps,
step: this.props.step,
}
}
renderAnswers = () => {
var answers = []
for (var i = 0; i < this.state.answers.length; i++) {
answers.push(
<WizardStepButton
answer={this.state.answers[i]}
updateStep={this.props.updateStep}
key={i}
/>
);
}
return answers;
}
render(){
return(
<View>
<Text style={styles.title}>Step {this.state.step + 1}/{this.state.totalSteps}</Text>
<Text style={styles.title}>{this.state.question}</Text>
{this.renderAnswers()}
</View>
)
}
}
const styles = StyleSheet.create({
title: {
marginTop: 30,
marginBottom: 30,
fontSize: 25,
color: 'rgba(96,100,109, 1)',
lineHeight: 24,
textAlign: 'center',
},
});
and the button component:
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { Button } from "react-native-elements";
import { Constants } from 'expo';
export default class WizardStepButton extends React.Component {
constructor(props){
super(props);
this.state ={
}
}
render(){
return(
<View>
<Button
style={{margin: 10}}
large
raised
title={this.props.answer}
onPress={() => this.props.updateStep(this.props.answer)}
/>
</View>
)
}
}
You should only increment state values by using a state updater function. - https://stackoverflow.com/a/45196079/874027
You're not spreading this.state.results before editing and putting them back into state.
Also the currentStep checks indexing looks off.
updateStep = answer => {
this.setState((state) => {
const { results, currentStep } = state
const newResults = [...results]
newResults[currentStep] = answer
return {
results: newResults,
currentStep: currentStep + 1,
}
}, () => {
const { currentStep, totalSteps } = this.state
if (currentStep + 1 === totalSteps) {
this.props.finish();
}
})
}
EDIT: in WizardStep component you're syncing props with state in constructor so when you try to pass the new props after you update your state, they'll never get reflected in the Wizard since its constructor has already fired off. You can either fix this by using props in your WizardStep component, or by passing it a key, so the new instance gets created every time the key changes, e.g.
<WizardStep
question={this.state.questions[this.state.currentStep]}
answers={this.state.answers[this.state.currentStep]}
step={this.state.currentStep}
totalSteps={this.state.totalSteps}
updateStep={this.updateStep}
key={this.state.currentStep}
/>
I've tested this locally and the steps do get changed with this approach.

TypeError: undefined is not an object(evaluating '_props.listMessagesQuery.listMessages') in ReactNative

Iam new to react-native and aws appsync.We are trying to display a list of messages.But when i run react-native run-android it is throwing an error saying
TypeError: undefined is not an object(evaluating '_props.listMessagesQuery.listMessages')
[Below is the screenshot url of the error]
https://i.stack.imgur.com/b1Wlj.png
Chat.js
import React,{Component} from 'react';
import ChatInput from './ChatInput';
import ChatMessages from './ChatMessages';
import { graphql, compose } from 'react-apollo';
import listMessages from './querys/listMessages';
import createMessage from './querys/createMessage';
import gql from 'graphql-tag';
import {
Platform,
StyleSheet,
Text,
View,
scrollIntoView
} from 'react-native';
class Chat extends Component {
state = {
message: '',
}
render() {
return (
<View className='Chat'>
<ChatMessages
messages={this.props.listMessagesQuery.listMessages || []}
endRef={this._endRef}
/>
<ChatInput
message={this.state.message}
onTextInput={(message) => this.setState({message})}
onResetText={() => this.setState({message: ''})}
onSend={this._onSend}
/>
</View>
);
}
_onSend = () => {
//console.log(`Send: ${this.state.message}`)
this.props.createMessageMutation({
variables: {
text: this.state.message,
sentById: this.props.userId
}
})
}
/*
* AUTO SCROLLING
*/
_endRef = (element) => {
this.endRef = element
}
componentDidUpdate(prevProps) {
// scroll down with every new message
if (prevProps.listMessagesQuery.listMessages !== this.props.listMessagesQuery.listMessages && this.endRef) {
this.endRef.scrollIntoView()
}
}
}
export default compose(
graphql(listMessages, {
options: {
fetchPolicy: 'cache-and-network'
},
props: (props) => ({
posts: props.listMessagesQuery.listMessages && props.listMessagesQuery.listMessages.Message,
})
}))(Chat)
App.js
import React,{ Component} from 'react';
import * as AWS from 'aws-sdk';
import {
Platform,
StyleSheet,
Text,
View
} from 'react-native';
import gql from 'graphql-tag';
import { graphql,compose} from 'react-apollo';
import generateStupidName from 'sillyname';
import localStorage from 'react-native-sync-localstorage';
import Chat from './Chat';
import { Async } from 'react-async-await';
import createPerson from './querys/createPerson';
const CHAT_USER_NAME_KEY = 'CHAT_USER_NAME'
const CHAT_USER_ID_KEY = 'CHAT_USER_ID'
class App extends Component {
async componentDidMount() {
let name = localStorage.getItem(CHAT_USER_NAME_KEY)
if (!name) {
name = generateStupidName()
const result = await this.props.createPersonMutation({
variables: { name }
})
localStorage.setItem(CHAT_USER_NAME_KEY, result.data.createPerson.name);
localStorage.setItem(CHAT_USER_ID_KEY, result.data.createPerson.id);
}
}
render() {
const name = localStorage.getItem(CHAT_USER_NAME_KEY)
const userId = localStorage.getItem(CHAT_USER_ID_KEY)
return (
<View style={styles.container}>
<Chat name={name} userId={userId} />
</View>
);
}
}
// const createPerson =gql`
// mutation createPerson($name:String!){
// createPerson(input :{
// name : $name
// }){
// id
// name
// }
// }
// `
// export default graphql(createPerson,{name:'createPersonMutation'})(App)
export default compose(
graphql(createPerson, {name:'createPersonMutation'}))(App)
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
Iam not understanding this error Please help me.Thanks! in Advance
Please check the format of
this.props.listMessagesQuery.listMessages
As the error defined that particular data or props you are passing are not an object.
console.log(this.props.listMessagesQuery.listMessages)
check if you find it in current formate. If you don't find anything share you this console.log result. Hope it helps you
you are not sending listMessagesQuery.listMessages as a props to Chat.js component you are only sending name and userId as props to Chat component
your existing code in App.js
<Chat name={name} userId={userId} />
you need to send
<Chat name={name} userId={userId} listMessagesQuery={}/>

Resources