I am building a react native app that uses the Wordpress api. I am having problems displaying the cart and receive this error.
Object {} error [Error: Request failed with status code 404]
undefined
I have tried everything and have figures it might be a problem with Axios...
Please advise me on what I can do...
CartAction.js
import * as types from '../constants/ActionTypes';
import CartApi from '../api/CartApi';
export function getCart() {
return (dispatch) => {
return CartApi.getCart().then(cart => {
dispatch(getCartSuccess(cart));
}).catch(err => {
//TODO:get correct error msg
console.log(err.error);
})
};
}
function getCartSuccess(cart) {
return {
type: types.GET_CART_SUCCESS,
cart
};
}
export function addToCart(product, quantity) {
return (dispatch) => {
return CartApi.addToCart(product, quantity).then(cartUpdate => {
dispatch(addToCartSuccess(cartUpdate));
}).catch(err => {
//TODO:get correct error msg
console.log('error',err);
})
};
}
function addToCartSuccess(cartUpdate) {
return {
type: types.ADD_TO_CART_SUCCESS,
cartUpdate
};
}
CartPage.js
import React from 'react'
import { StyleSheet, Text, View, FlatList, Image } from 'react-native'
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as CartAction from '../../actions/CartAction';
class CartPage extends React.Component {
constructor(props) {
super(props);
this.state = {
cart: {}
}
}
componentDidMount() {
this.props.CartAction.getCart();
}
_keyExtractor = (item, index) => item.key;
render() {
console.log(this.props.cart)
const cartObject = this.props.cart;
var cartArray = [];
Object.keys(cartObject).forEach(function(key) {
cartArray.push(cartObject[key]);
});
const Items = <FlatList contentContainerStyle={styles.list}
data={cartArray}
keyExtractor={this._keyExtractor}
renderItem={({ item }) =>
// <TouchableHighlight style={{width:'50%'}} onPress={() => navigate("Product", { product: item })} underlayColor="white">
<View style={styles.lineItem} >
<Image style={styles.image} source={{uri: item.product_image}} />
<Text style={styles.text}>{item.product_name}</Text>
<Text style={styles.text}>{item.quantity}</Text>
</View>
// </TouchableHighlight>
}
/>;
return (
<View style={styles.container}>
{Items}
</View>
)
}
}
const styles = StyleSheet.create({
lineItem: {
flexDirection: 'row'
},
list: {
flexDirection: 'column'
},
image: {
width: 50,
height: 50
},
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
text: {
fontSize: 20,
padding: 5
}
})
function mapStateToProps(state) {
return {
cart: state.cart
};
}
function mapDispatchToProps(dispatch) {
return {
CartAction: bindActionCreators(CartAction, dispatch)
};
}
export default connect(mapStateToProps, mapDispatchToProps)(CartPage);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
Related
I am adding a unique key to the FlatList and in theory only the button i press is supposed to be deleted but instead all elements are deleted
import { render } from "react-dom";
import {
View,
Text,
StyleSheet,
FlatList,
Button,
TouchableOpacity,
} from "react-native";
import { Context } from "../context/BlogContext";
import { Entypo } from "#expo/vector-icons";
const IndexScreen = function () {
const { state, addBlogPost, deleteBlogPost } = useContext(Context);
return (
<View>
<Button title="Add Post" onPress={() => addBlogPost()} />
<FlatList
data={state}
keyExtractor={(blogPosts) => blogPosts.title}
renderItem={({ item }) => {
return (
<View style={styles.row}>
<Text style={styles.title}>
{item.title} - {item.id}
</Text>
<TouchableOpacity
onPress={() => {
deleteBlogPost(item.id);
}}
>
<Entypo style={styles.icon} name="trash" />
</TouchableOpacity>
</View>
);
}}
/>
</View>
);
};
const styles = StyleSheet.create({
row: {
flexDirection: "row",
justifyContent: "space-between",
paddingHorizontal: 10,
paddingVertical: 20,
borderTopWidth: 1,
borderColor: "gray",
},
title: {
fontSize: 18,
},
icon: {
fontSize: 24,
},
});
export default IndexScreen;
Context Screen:
import createDataContext from "./createDataContext";
const blogReducer = function (state, action) {
switch (action.type) {
case "delete_blogpost":
return state.filter((blogPosts) => {
blogPosts.id !== action.payload;
});
case "add_blogpost":
return [
...state,
{
id: Math.floor(Math.random() * 99999),
title: `Blog Post #${state.length + 1}`,
},
];
default:
return state;
}
};
const addBlogPost = function (dispatch) {
return () => {
dispatch({ type: "add_blogpost" });
};
};
const deleteBlogPost = (dispatch) => {
return (id) => {
dispatch({ type: "delete_blogpost", payload: id });
};
};
export const { Context, Provider } = createDataContext(
blogReducer,
{ addBlogPost, deleteBlogPost },
[]
);
and
export default function (reducer, actions, initialState) {
const Context = React.createContext();
const Provider = ({ children }) => {
const [state, dispatch] = useReducer(reducer, initialState);
// actions === { addBlogPost : (dispatch) => {return () => {}}}
const boundActions = {};
for (let key in actions) {
boundActions[key] = actions[key](dispatch);
}
return (
<Context.Provider value={{ state, ...boundActions }}>
{children}
</Context.Provider>
);
};
return { Context, Provider };
}
i dont know how to solve this. all titles are unique as they have different numbers but still all are deleted!!!!!!!!!!!!
here is the pic of the app
I followed a tutorial on youtube.
I wrote the same he did, but I'm facing this issue
ERROR: Actions must be plain objects. Use custom middleware for async
functions
Store/index.js
import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import rootReducer from '../reducers'
export default function configureStore() {
let store = createStore(
rootReducer,
applyMiddleware(thunk)
);
return store
}
actions/index.js
import { ADD_TODO, TOGGLE_TODO } from './ActionTypes'
let nextId = 0
export const addTodo = (text) => ({
type: ADD_TODO,
id: nextId++,
text
})
export const toggleTodo = (di) => ({
type: TOGGLE_TODO_,
id
})
reducers/index.js
import { combineReducers } from "redux";
import todosReducer from './todosReducer'
import visibiltyReducer from './visibiltyReducer'
const rootReducer = combineReducers({
todosReducer,
visibiltyReducer
})
export default rootReducer
reducers/todoreducer.js
import { ADD_TODO, TOGGLE_TODO } from '../actions/ActionTypes'
const todosReducer = (state = [], action) => {
console.log("TODO Reducer: " + action.type)
switch (action.type) {
case ADD_TODO:
return [
...state, {
id: action.id,
text: action.text,
completed: false
},
]
case TOGGLE_TODO:
return state.map(todo => (todo.id == action.id) ? { ...todo, completed: !todo.completed } : todo)
default:
return state
}
}
export default todosReducer
App.js
render() {
return (
<View style={styles.container}>
<Provider store={store}>
<TodoApp />
</Provider>
</View>
);
}
As using dispatch showing the issue at dispatch line. Please help where I went wrong.
import React, { Component } from "react";
import {
View,
TextInput,
StyleSheet,
TouchableOpacity
} from "react-native";
import { Icon } from "native-base";
import { connect } from 'react-redux'
import addTodo from '../redux/actions'
let nextId = 0
class AddTodo extends Component {
constructor(props) {
super(props)
this.state = {
text: ''
}
}
addingTodo = (text) => {
// alert("TODO " + text)
if (text.length > 0) {
this.props.dispatch({ type: "ADD_TODO", id: nextId++, text: text })
// this.props.dispatch(addTodo(text))
alert("TODO Added")
this.setState({ text: '' })
} else alert("Can't add empty")
}
render() {
return (
<View style={{ flexDirection: 'row', width: '100%' }}>
<View style={styles.container}>
<TextInput
value={this.state.text}
placeholder="Add ToDo"
onChangeText={(text) => this.setState({ text })}
style={{ height: 50, flex: 1, backgroundColor: '#dddddd' }}
/>
<TouchableOpacity
onPress={() => this.addingTodo(this.state.text)}>
<Icon
name='md-add-circle'
size={30} style={{ color: '#3456ff', backgroundColor: 'white', borderRadius: 20 }} />
</TouchableOpacity>
</View>
</View >
);
}
}
export default connect()(AddTodo);
const styles = StyleSheet.create({
container: {
marginStart: 10,
marginEnd: 10,
width: '100%',
height: 60,
alignItems: 'center',
justifyContent: 'center',
padding: 15,
flexDirection: 'row',
backgroundColor: '#dddddd',
}
});
<--it shows data.source error-->
import React, { Component } from "react";
import { AppRegistry, StyleSheet, View, Platform, Picker, ActivityIndicator, Button, Alert} from "react-native";
export default class Project extends Component {
constructor(props)
{
super(props);
this.state = {
isLoading: true,
PickerValueHolder : ""
}; }
componentDidMount() {
return fetch("https://facebook.github.io/react-native/movies.json")
.then((response) => response.json())
.then((responseJson) => {
this.setState({
isLoading: false,
dataSource: responseJson
}, function() {
// In this block you can do something with new state.
});
})
.catch((error) => {
console.error(error);
});}
GetPickerSelectedItemValue=()=>{
Alert.alert(this.state.PickerValueHolder);
}
render() {
if (this.state.isLoading) {
return (
<View style={{flex: 1, paddingTop: 20}}>
<ActivityIndicator />
</View>`help needed`
);
}
return (
<View style={styles.MainContainer}>
<Picker
selectedValue={this.state.PickerValueHolder}
onValueChange={(itemValue, itemIndex) => this.setState({PickerValueHolder: itemValue})} >
{ this.state.dataSource.map((item, key)=>(
<Picker.Item label={item.title} value={item.title} key={key} />)
)}
</Picker>
<Button title="Click Here To Get Picker Selected Item Value" onPress={ this.GetPickerSelectedItemValue } />
</View>
);}}
const styles = StyleSheet.create({
MainContainer :{
justifyContent: "center",
flex:1,
margin: 10
}});
import React, { Component } from "react";
import { ListView, Text, StyleSheet, View, ActivityIndicator, Button, Alert} from "react-native";
export default class Project extends Component {
constructor(props)
{
super(props);
this.state = {
isLoading: true,
PickerValueHolder : "",
language: ''
};
}
GetPickerSelectedItemValue(value: string) {
Alert.alert(value);
this.setState({
selected: value
});
}
GetItem (title) {
Alert.alert(title);
}
componentDidMount() {
return fetch('https://facebook.github.io/react-native/movies.json')
.then((response) => response.json())
.then((responseJson) => {
let ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
this.setState({
isLoading: false,
dataSource: ds.cloneWithRows(responseJson['movies']),
}, function() {
// In this block you can do something with new state.
});
})
.catch((error) => {
console.error(error);
});
}
ListViewItemSeparator = () => {
return (
<View
style={{
height: .5,
width: "100%",
backgroundColor: "#000",
}}
/>
);
}
render() {
if (this.state.isLoading) {
return (
<View style={{flex: 1, paddingTop: 20}}>
<ActivityIndicator />
</View>
);
}
return (
<View style={styles.MainContainer}>
<ListView
dataSource={this.state.dataSource}
renderSeparator= {this.ListViewItemSeparator}
renderRow={(rowData) =>
<View style={{flex:1, flexDirection: 'row'}}>
<Text onPress={this.GetItem.bind(this, rowData.title)} style={styles.textViewContainer} >{rowData.title}</Text>
</View>
}
/>
</View>
);
}
}
const styles = StyleSheet.create({
MainContainer :{
justifyContent: "center",
flex:1,
margin: 10
}
});
I am facing 2 issues related to length of my selected photos:
When selecting photos, it lets me to select 5 photos without any issue (it fits my length restriction), however it doesn't save the chosen photos, when I go to the next screen. In another scenario, when I am at the same screen where I choose photos and I choose 6 photos, it selects the 6 photo but the warning popup will appear and say that its currently supports 5, then when I go to next screen its saves the selected photos unlike previously.
If I deselect photos and then try to select another photos (still in my length limit) popup jumps with selection limit and doesn't let me choose photos, when I go to the next screen it saves the changes from previous selection and not from current one.
import React from 'react';
import {
View,
ScrollView,
Image,
Dimensions,
TextInput,
Text,
StatusBar,
TouchableHighlight,
Linking,
Keyboard,
CameraRoll,
KeyboardAvoidingView
} from 'react-native';
import {connect} from 'react-redux';
import {ActionCreators} from '../redux/actions';
import {bindActionCreators} from 'redux';
import Colors from '../constants/Colors';
import api from '../api';
import {
getEmailAddress,
showError,
renderMessageBar,
registerMessageBar,
unregisterMessageBar
} from '../utils/ComponentUtils';
import {
regularHeader,
mainHeader
} from '../utils/Headers';
import {NavigationActions} from 'react-navigation';
import {SelectionLimitDialog} from '../utils/Dialogs';
import {ifIphoneX, isIphoneX} from 'react-native-iphone-x-helper';
import {SafeAreaView} from 'react-navigation';
// specific component imports.
import {List, ListItem} from 'react-native-elements'
import {Button} from 'react-native-elements'
import Loader from '../components/Loader';
import LoaderError from '../components/LoaderError';
import SelectedPhoto from '../components/SelectedPhoto';
class MultiSafeeScreen extends React.Component
{
static navigationOptions = ({navigation}) => {
const {params} = navigation.state;
const isIncome = params ? params.isIncome : false;
const notificationAction = params ? params.notificationAction : () => {};
const isShowBack = params ? params.isShowBack : false;
return mainHeader({
isShowBack: isShowBack,
backAction: () => navigation.goBack(),
notificationAction: () => notificationAction(),
income: isIncome
});
};
constructor(props) {
super(props);
this.selectedPhotos = [];
this.state = {
photos: null,
loader: {
loading: 0,
message: "Loading photos..."
},
selectedPhotos: [],
supportLength: 5
};
this.props.navigation.setParams({notificationAction: this.onNotification, isIncome: this.props.isNewNotifications});
}
UNSAFE_componentWillReceiveProps(newProps) {
if (newProps.isNewNotifications !== this.props.isNewNotifications) {
this.props.navigation.setParams({notificationAction: this.onNotification, isIncome: newProps.isNewNotifications});
}
}
componentDidMount() {
registerMessageBar(this.refs.alert);
let options = {
first: 30,
assetType: 'Photos',
}
CameraRoll.getPhotos(options)
.then(r => {
this.setState({
photos: r.edges,
loader: {
loading: 1,
message: "Loading photos..."
},
});
})
.catch((err) => {
//Error Loading Images
});
StatusBar.setHidden(false);
}
componentWillUnmount() {
unregisterMessageBar();
this.props.setSelectedPhotos(0);
}
onNotification = () => {
this.props.setNewNotifications(false);
this.props.navigation.navigate("Notifications");
}
closeKeyboard = () => {
Keyboard.dismiss();
}
onSelectPhoto = (photo, index) => {
let photos = new Set([...this.selectedPhotos]);
let len = photos.size + 1 ;
console.log('photos')
if (len > this.state.supportLength) {
this.limitDialog.open();
this.setState({selectedPhotos: this.selectedPhotos});
this.props.setSelectedPhotos(len);
}
else {
photos.add(photo);
this.selectedPhotos = Array.from(photos);
}
}
onDeselectPhoto = (photo, index) => {
let photos = new Set([...this.state.selectedPhotos]);
let len = photos.size - 1;
photos.delete(photo);
this.setState({selectedPhotos: Array.from(photos)});
this.props.setSelectedPhotos(len);
}
onNext = () => {
this.props.navigation.navigate("MultiSafeeCreate", {
isShowBack: true,
selected: [...this.state.selectedPhotos]
});
}
renderLoader() {
let {width, height} = Dimensions.get('window');
let photoWidth = width/3;
if (this.state.loader.loading === 0) {
return <Loader style={{justifyContent: 'center', alignItems: 'center'}} message={this.state.loader.message}/>
}
else if (this.state.loader.loading === 2) {
return <LoaderError style={{justifyContent: 'center', alignItems: 'center'}} message={this.state.loader.message}/>
}
// if photos are null do nothing, else if empty show onbording
// if has photos show photos.
if (this.state.photos === null) {
return <Loader style={{justifyContent: 'center', alignItems: 'center'}} message={this.state.loader.message}/>
}
else {
return (
<View style={{width: width, maxHeight: 600}}>
<ScrollView >
<View style={{flexDirection: 'row', width: width, flexWrap: 'wrap',marginBottom:40, justifyContent: 'space-between'}}>
{
this.state.photos.map((p, i) => {
return (
<SelectedPhoto
key={i}
index={i}
style={{
width: photoWidth,
height: photoWidth,
}}
borderColor = "white"
limit={this.state.supportLength}
photo={p}
onSelectPhoto={this.onSelectPhoto}
onDeselectPhoto={this.onDeselectPhoto}
/>
);
})
}
</View>
</ScrollView>
<View style={{ position:'absolute', right:-15, top:475 }}>
<Button
onPress={this.onNext}
containerViewStyle={{width: width}}
backgroundColor={Colors.red}
title='NEXT' />
</View>
</View>
);
}
}
render() {
return (
<View style={{flex: 1, backgroundColor: Colors.white}}>
{this.renderLoader()}
<SelectionLimitDialog ref={(el) => this.limitDialog = el} />
{renderMessageBar()}
</View>
);
}
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(ActionCreators, dispatch);
}
function mapStatesToProps(state) {
return {
isNewNotifications: state.isNewNotifications
};
}
export default connect(mapStatesToProps, mapDispatchToProps)(MultiSafeeScreen);
The problem is that the React Native App display will not display the contents of the JSON string stored in getMovies(). The display logic in getMovies() does not recognize a Text to print out, and only displays [object Object] with out any contents.
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View
} from 'react-native';
const instructions = Platform.select({
ios: 'Press Cmd+R to reload,\n' +
'Cmd+D or shake for dev menu',
android: 'Double tap R on your keyboard to reload,\n' +
'Shake or press menu button for dev menu',
});
export default class App extends Component<{}> {
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit App.js
</Text>
<Text style={styles.instructions}>
{instructions}
</Text>
<Text>{getMovies().toString()}</Text>
</View>
);
}
}
function getMovies() {
var movies = getMoviesFromApiAsync();
return movies;
}
function getMoviesFromApiAsync() {
return fetch('https://facebook.github.io/react-native/movies.json')
.then((response) => response.json())
.then((responseJson) => {
return responseJson.movies;
})
.catch((error) => {
console.error(error);
});
}
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,
},
});
Without a custom toString() implementation, calling toString() on an object will follow the prototype chain up to the Object prototype toString method, which simply prints out [object Object] like you are seeing.
You can either:
Replace getMovies().toString() with JSON.stringify(getMovies()), which will get you closer to what you want, but it will have curly braces included in the string.
Replace getMovies().toString() with a custom renderer like Object.values(getMovies()).map(movie => <MovieDetails movie={movie} />) where you have built your own MovieDetails component.
The problem with that is that the function getMovies() return a promise and its value it's not resolved until is being execute and then call the then() function. This is the solution:
export default class App extends Component {
state = {
movies: [],
}
componentDidMount() {
getMovies().then(movies => this.setState({ movies: movies.map(movie => movie.title).join(', ') }));
}
render() {
const { movies } = this.state;
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to React Native!
</Text>
<Text style={styles.instructions}>
To get started, edit App.js
</Text>
<Text style={styles.instructions}>
{instructions}
</Text>
<Text>{movies}</Text>
</View>
);
}
}
You can view this here https://repl.it/repls/RashBowedHarpyeagle
import React, { Component } from 'react';
import { Platform, StyleSheet, Text, View } from 'react-native';
export default class App extends Component<{}> {
constructor(props){
super(props)
this.state = {
movies: []
}
}
componentDidMount(){
this.getMovies()
}
getMovies = () => {
this.getMoviesFromApiAsync()
.then(movies => {
console.log(movies)
this.setState({
movies
})
})
}
getMoviesFromApiAsync = () => {
return fetch('https://facebook.github.io/react-native/movies.json')
.then(response=> response.json())
.then(responseJson => responseJson.movies)
.catch(error => console.error(error));
}
render() {
return (
<View style={styles.container}>
{
this.state.movies.map((movie, index) => {
return <Text key = {index}>{movie.title}<Text>{movie.releaseYear}</Text></Text>
})
}
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
}
});