redux的新手,并试图构建一个简单的购物车。从教程中,我得到了redux的基本布局。所以我创造了其中的一些
home.js
'use strict';
import React, { Component } from 'react';
import {
StyleSheet,
FlatList,
View,
Text,
Button,
ActivityIndicator
} from 'react-native';
import {bindActionCreators} from 'redux';
import { connect } from 'react-redux';
import * as Actions from '../actions'; //Import your actions
class Home extends Component {
constructor(props) {
super(props);
this.state = {
};
this.renderItem = this.renderItem.bind(this);
}
componentDidMount() {
this.props.getData(); //call our action
}
static navigationOptions = {
title: "Test",
headerStyle: {
backgroundColor: '#4050B5',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold'
}
};
render() {
if (this.props.loading) {
return (
<View style={styles.activityIndicatorContainer}>
<ActivityIndicator animating={true}/>
</View>
);
} else {
return (
<View style={{flex:1, backgroundColor: '#F5F5F5', paddingTop:20}}>
<FlatList
ref='listRef'
data={this.props.data}
renderItem={this.renderItem}
keyExtractor={(item, index) => item.sno+item.name}/>
<Button
onPress={() => {this.props.navigation.navigate('Cart')}}
title="View Cart"
color="#841584"
/>
</View>
);
}
}
renderItem({item, index}) {
return (
<View style={styles.row}>
<Text style={styles.title}>
{(parseInt(index) + 1)}{". "}{item.name}
</Text>
<Text style={styles.description}>
{item.ver}
</Text>
<Button
onPress={() => {this.props.testFunc(item)}}
title="Add to Cart"
color="#4050B5"
/>
</View>
)
}
};
// The function takes data from the app current state,
// and insert/links it into the props of our component.
// This function makes Redux know that this component needs to be passed a piece of the state
function mapStateToProps(state, props) {
return {
loading: state.dataReducer.loading,
data: state.dataReducer.data
}
}
// Doing this merges our actions into the component’s props,
// while wrapping them in dispatch() so that they immediately dispatch an Action.
// Just by doing this, we will have access to the actions defined in out actions file (action/home.js)
function mapDispatchToProps(dispatch) {
return bindActionCreators(Actions, dispatch);
}
//Connect everything
export default connect(mapStateToProps, mapDispatchToProps)(Home);
const styles = StyleSheet.create({
activityIndicatorContainer:{
backgroundColor: "#fff",
alignItems: 'center',
justifyContent: 'center',
flex: 1,
},
row:{
borderBottomWidth: 1,
borderColor: "#ccc",
padding: 10
},
title:{
fontSize: 15,
fontWeight: "600"
},
description:{
marginTop: 5,
fontSize: 14,
}
});
reducer index.js
import { combineReducers } from 'redux';
import { DATA_AVAILABLE,
ADD_TO_CART
} from "../actions/" //Import the actions types constant we defined in our actions
let dataState = { data: [], loading:true };
let cartState = { data: [] };
const dataReducer = (state = dataState, action) => {
switch (action.type) {
case DATA_AVAILABLE:
state = Object.assign({}, state, { data: action.data, loading:false });
return state;
default:
return state;
}
};
const cartReducer = (state = cartState, action) => {
switch (action.type) {
case ADD_TO_CART:
state = Object.assign({}, state, { data: action.data});
console.log("state data => "+state.data);
return state;
default:
return state;
}
};
// Combine all the reducers
const rootReducer = combineReducers({
dataReducer,
cartReducer
// ,[ANOTHER REDUCER], [ANOTHER REDUCER] ....
})
export default rootReducer;
action index.js
export const DATA_AVAILABLE = 'DATA_AVAILABLE';
export const ADD_TO_CART = "ADD_TO_CART";
//Import the sample data
import Data from '../instructions.json';
export function getData(){
return (dispatch) => {
//Make API Call
//For this example, I will be using the sample data in the json file
//delay the retrieval [Sample reasons only]
/*
setTimeout(() => {
const data = Data.instructions;
dispatch({type: DATA_AVAILABLE, data:data});
}, 2000);
*/
fetch('https://tetapi-cart.com?vers[]=dc')
.then((response) => response.json())
.then((responseJson) => {
dispatch({type: DATA_AVAILABLE, data:responseJson.result});
})
.catch((error) => {
console.error(error);
});
};
}
export function testFunc(user){
return (dispatch) => {
dispatch({type: ADD_TO_CART, data:user});
console.log(user);
};
}
cart.js
'use strict';
import React, { Component } from 'react';
import {
StyleSheet,
FlatList,
View,
Text,
Button,
ActivityIndicator
} from 'react-native';
import {bindActionCreators} from 'redux';
import { connect } from 'react-redux';
import * as Actions from '../actions'; //Import your actions
class Cart extends Component {
constructor(props) {
super(props);
this.state = {
};
this.renderItem = this.renderItem.bind(this);
}
componentDidMount() {
//this.props.getData(); //call our action
}
static navigationOptions = {
title: "Your Shopping Cart",
headerStyle: {
backgroundColor: '#4050B5',
},
headerTintColor: '#fff',
headerTitleStyle: {
fontWeight: 'bold'
}
};
render() {
if (this.props.data == "") {
return (
<View style={{flex:1, backgroundColor: '#F5F5F5', paddingTop:20}}>
<Text>Shopping cart is empty</Text>
</View>
);
} else {
return (
<View style={{flex:1, backgroundColor: '#F5F5F5', paddingTop:20}}>
<Text>Shopping has something</Text>
<FlatList
ref='listCartRef'
data={this.props.data}
renderItem={this.renderItem}
keyExtractor={(item, index) => item.sno+item.name}/>
</View>
);
}
}
renderItem({item, index}) {
return (
<View style={styles.row}>
<Text style={styles.title}>
{(parseInt(index) + 1)}{". "}{item.name}
</Text>
<Text style={styles.description}>
{item.ver}
</Text>
<Button
onPress={() => {this.props.testFunc(item)}}
title="Add to Cart"
color="#4050B5"
/>
</View>
)
}
};
// The function takes data from the app current state,
// and insert/links it into the props of our component.
// This function makes Redux know that this component needs to be passed a piece of the state
function mapStateToProps(state, props) {
return {
data: state.cartReducer.data
}
}
// Doing this merges our actions into the component’s props,
// while wrapping them in dispatch() so that they immediately dispatch an Action.
// Just by doing this, we will have access to the actions defined in out actions file (action/home.js)
function mapDispatchToProps(dispatch) {
return bindActionCreators(Actions, dispatch);
}
//Connect everything
export default connect(mapStateToProps, mapDispatchToProps)(Cart);
const styles = StyleSheet.create({
activityIndicatorContainer:{
backgroundColor: "#fff",
alignItems: 'center',
justifyContent: 'center',
flex: 1,
},
row:{
borderBottomWidth: 1,
borderColor: "#ccc",
padding: 10
},
title:{
fontSize: 15,
fontWeight: "600"
},
description:{
marginTop: 5,
fontSize: 14,
}
});
问题出在cart.js上,我无法通过点击此错误来呈现flatlist
**`TaskQueue: Error with task : Invariant Violation: Invariant Violation: Tried to get frame for out of range index NaN`**
我检查了一下,看不到任何问题。不确定我在购物车数据上哪一部分做错了吗?而且我也在尝试合并我购物车的数据,也不确定该怎么做。
答案 0 :(得分:0)
我发现我的阵列有问题,我设法解决了这个问题,因为我添加到购物车中的阵列格式不正确,这导致了平面列表错误