TypeError: Cannot read property 'map' of undefined React Native Redux
TypeError: Cannot read property 'map' of undefined React Native Redux
我试图创建一个减速器,遵循与我使用 git repos
的示例相同的逻辑
这里说reducer:
/**
* Created by kenji on 3/9/18.
*/
/**
* /stock?search=String
* Searches Stock table, checking for given search value
* and returns an array that contains that value
* @action GET
* @returns [array]
* @type {string}
*/
export const GET_STOCK_LIST = 'ReduxStarter/stock_list/LOAD';
export const GET_STOCK_LIST_SUCCESS = 'ReduxStarter/stock_list/LOAD_SUCCESS';
export const GET_STOCK_LIST_FAIL = 'ReduxStarter/stock_list/LOAD_FAILURE';
/**
* /stock/${id}
* Gets an ID passed to it and returns an object if it exists
* @action GET
* @returns {object}
* @type {string}
*/
export const GET_STOCK = 'ReduxStarter/stock/LOAD';
export const GET_STOCK_SUCCESS = 'ReduxStarter/stock/LOAD_SUCCESS';
export const GET_STOCK_FAIL = 'ReduxStarter/stock/LOAD_FAIL';
/**
* /stock/${id}
* Updates Stock by passing an object with new variables to update with
* @action PUT
* @returns {null}
* @type {string}
*/
export const PUT_STOCK = 'ReduxStarter/stock/CHANGE';
export const PUT_STOCK_SUCCESS = 'ReduxStarter/stock/CHANGE_SUCCESS';
export const PUT_STOCK_FAIL = 'ReduxStarter/stock/CHANGE_FAIL';
/**
* /stock/${id}/barcodes
* Gets the barcodes of an a stock item if the ID is valid
* @action: GET
* @returns [array]
* @type {string}
*/
export const GET_BARCODES = 'ReduxStarter/stock/barcodes/LOAD';
export const GET_BARCODES_SUCCESS = 'ReduxStarter/stock/barcodes/LOAD_SUCCESS';
export const GET_BARCODES_FAIL = 'ReduxStarter/stock/barcodes/LOAD_FAIL';
/**
* /stock/barcode/${barcode}
* Gets a stock item from the supplied barcode
* @action: GET
* @returns [array]
* @type {string}
*/
export const GET_STOCK_FROM_BARCODE = 'ReduxStarter/stock/barcode/LOAD';
export const GET_STOCK_FROM_BARCODE_SUCCESS = 'ReduxStarter/stock/barcode/LOAD_SUCCESS';
export const GET_STOCK_FROM_BARCODE_FAIL = 'ReduxStarter/stock/barcode/LOAD_FAIL';
const initialState = {
stockList: [],
stock: {},
result: {},
barcodeList: [],
stockFromBarcode: {},
};
export default function reducer(state = initialState, action) {
switch(action.type) {
case GET_STOCK_LIST:
return { ...state, loadingStockList: true };
case GET_STOCK_LIST_SUCCESS:
return { ...state, loadingStockList: false, stockList: action.payload.data };
case GET_STOCK_LIST_FAIL:
return { ...state, loadingStockList: false, stockListError: 'Failed to retrieve stock list' };
case GET_STOCK:
return { ...state, loadingStock: true };
case GET_STOCK_SUCCESS:
return { ...state, loadingStock: false, stock: action.payload.data };
case GET_STOCK_FAIL:
return { ...state, loadingStock: false, stockError: 'Failed to retrieve stock list' };
case PUT_STOCK:
return { ...state, loadingStockUpdate: true };
case PUT_STOCK_SUCCESS:
return { ...state, loadingStockUpdate: false, result: action.payload.data };
case PUT_STOCK_FAIL:
return { ...state, loadingStockUpdate: false, stockUpdateError: 'Failed to update stock list' };
case GET_BARCODES:
return { ...state, loadingBarcodes: true };
case GET_BARCODES_SUCCESS:
return { ...state, loadingBarcodes: false, barcodeList: action.payload.data };
case GET_BARCODES_FAIL:
return { ...state, loadingBarcodes:false, barcodesError: 'Failed to load barcodes' };
case GET_STOCK_FROM_BARCODE:
return { ...state, loadingStockFromBarcode: true };
case GET_STOCK_FROM_BARCODE_SUCCESS:
return { ...state, loadingStockFromBarcode: false, stockFromBarcode: action.payload.data };
case GET_STOCK_FROM_BARCODE_FAIL:
return { ...state, loadingStockFromBarcode: false, stockFromBarcodeError: 'Failed to get stock item from barcode' };
default:
return state;
}
}
export function listStockArray(searchQuery, pageSize = 50, pageNumber = 1) {
return {
type: GET_STOCK_LIST,
payload: {
request: {
url: `/stock?search=${searchQuery}&pageSize=${pageSize}&pageNumber=${pageNumber}`
}
}
};
}
export function listStockItem(stockID) {
return {
type: GET_STOCK_LIST,
payload: {
request: {
url: `/stock/${stockID}`
}
}
};
}
export function updateStock(stockID, data) {
return {
type: GET_STOCK_LIST,
payload: {
request: {
url: `/stock/${stockID}`,
method: `PUT`,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
data: data,
}
}
};
}
export function listStockBarcodes(stockID) {
return {
type: GET_BARCODES,
payload: {
request: {
url: `/stock/${stockID}/barcodes`
}
}
};
}
export function listStockFromBarcode(barcode) {
return {
type: GET_BARCODES,
payload: {
request: {
url: `/stock/barcode/${barcode}`
}
}
};
}
现在我收到 header 中提到的错误:
**类型错误:无法读取未定义的 属性 'map' **
这里是减速器对应用程序的实现:
import reducers from './redux/reducers/lots_reducer';
import StockList from './components/StockList';
const client = axios.create({
baseURL: 'https://api.github.com',
responseType: 'json'
});
const store = createStore(reducers, applyMiddleware(axiosMiddleware(client)));
const Stack = createStackNavigator({
StockList: {
screen: StockList
},
});
export default class App extends Component {
render() {
return (
<Provider store={store}>
<View style={styles.container}>
<Stack/>
</View>
</Provider>
);
}
}
最后是实际组件:
import { connect } from 'react-redux';
import { listStockArray } from '../redux/reducers/lots_reducer';
class StockList extends Component {
componentDidMount() {
this.props.listStockArray('panadol');
}
renderItem = ({ stockList }) => (
<TouchableOpacity
style={styles.item}
onPress={() => this.props.navigation.navigate(`Detail`, { name: stockList.StockID })}
>
<Text>{stockList.TradeName}</Text>
</TouchableOpacity>
);
render() {
const { stockList } = this.props;
return (
<FlatList
styles={styles.container}
data={stockList}
renderItem={this.renderItem}
/>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1
},
item: {
padding: 16,
borderBottomWidth: 1,
borderBottomColor: '#ccc'
}
});
const mapStateToProps = state => {
let storedRepositories = state.repos.map(repo => ({ key: (repo.id).toString(), ...repo }));
return {
repos: storedRepositories
};
};
const mapDispatchToProps = {
listStockArray
};
export default connect(mapStateToProps, mapDispatchToProps)(StockList);
对于转储的大量代码感到抱歉,它只是所有相关的,我相信错误出在某个地方有一个未定义的 initialState 但我看不到我错过了什么定义
您似乎没有定义 repos
,您想如何映射它?
const initialState = {
stockList: [],
stock: {},
result: {},
barcodeList: [],
stockFromBarcode: {},
repos: []
};
或者,您指的是另一个字段。
因为您尝试使用 map
函数来处理数组,但您 repo
不是数组。
有可能 repo
不是当你是 mapping
它(可能在赋值之前)。
Approach 我只是使用 Array.isArray()
检查它在哪里是一个数组,如果是数组,则可能 return 空数组。
正如@sagi 提到的,更好的方法是将 repo
字段初始化为空数组。基本上,这种错误发生在
you try to use array function to non-array element
这个代码
const mapStateToProps = state => {
let storedRepositories = state.repos.map(repo => ({ key: (repo.id).toString(), ...repo }));
return {
repos: storedRepositories
};
};
意味着你想要转换(将 id
更改为 key
属性)state.repos 使用 map 函数和 return 作为 repos
使用中间变量 storedRepositories
。这些部分看起来是原始的,没有从 repos 示例中更改。
出现错误是因为状态不包含 repos
数组。您还有一些其他数组处于状态(reducer 中的 initialState),但其中 none 是 repos
.
在 reducer 中,您将有效负载(获取的数据)存储在存储数组中,f.e。
case GET_STOCK_LIST_SUCCESS:
return { ...state, loadingStockList: false, stockList: action.payload.data };
将数据存储在 stockList
中。对于其他成功操作,您有其他数组名称。
组件不必使用所有存储数据,您可以只使用它感兴趣的部分 - 这是 mapStateToProps
映射的原因。您可以像
一样简单
const mapStateToProps = state => {
return {
stockList: state.stockList,
stock: state.stock
};
};
这些值将以 this.props.stockList
和 this.props.stock
的形式提供。
我试图创建一个减速器,遵循与我使用 git repos
的示例相同的逻辑这里说reducer:
/**
* Created by kenji on 3/9/18.
*/
/**
* /stock?search=String
* Searches Stock table, checking for given search value
* and returns an array that contains that value
* @action GET
* @returns [array]
* @type {string}
*/
export const GET_STOCK_LIST = 'ReduxStarter/stock_list/LOAD';
export const GET_STOCK_LIST_SUCCESS = 'ReduxStarter/stock_list/LOAD_SUCCESS';
export const GET_STOCK_LIST_FAIL = 'ReduxStarter/stock_list/LOAD_FAILURE';
/**
* /stock/${id}
* Gets an ID passed to it and returns an object if it exists
* @action GET
* @returns {object}
* @type {string}
*/
export const GET_STOCK = 'ReduxStarter/stock/LOAD';
export const GET_STOCK_SUCCESS = 'ReduxStarter/stock/LOAD_SUCCESS';
export const GET_STOCK_FAIL = 'ReduxStarter/stock/LOAD_FAIL';
/**
* /stock/${id}
* Updates Stock by passing an object with new variables to update with
* @action PUT
* @returns {null}
* @type {string}
*/
export const PUT_STOCK = 'ReduxStarter/stock/CHANGE';
export const PUT_STOCK_SUCCESS = 'ReduxStarter/stock/CHANGE_SUCCESS';
export const PUT_STOCK_FAIL = 'ReduxStarter/stock/CHANGE_FAIL';
/**
* /stock/${id}/barcodes
* Gets the barcodes of an a stock item if the ID is valid
* @action: GET
* @returns [array]
* @type {string}
*/
export const GET_BARCODES = 'ReduxStarter/stock/barcodes/LOAD';
export const GET_BARCODES_SUCCESS = 'ReduxStarter/stock/barcodes/LOAD_SUCCESS';
export const GET_BARCODES_FAIL = 'ReduxStarter/stock/barcodes/LOAD_FAIL';
/**
* /stock/barcode/${barcode}
* Gets a stock item from the supplied barcode
* @action: GET
* @returns [array]
* @type {string}
*/
export const GET_STOCK_FROM_BARCODE = 'ReduxStarter/stock/barcode/LOAD';
export const GET_STOCK_FROM_BARCODE_SUCCESS = 'ReduxStarter/stock/barcode/LOAD_SUCCESS';
export const GET_STOCK_FROM_BARCODE_FAIL = 'ReduxStarter/stock/barcode/LOAD_FAIL';
const initialState = {
stockList: [],
stock: {},
result: {},
barcodeList: [],
stockFromBarcode: {},
};
export default function reducer(state = initialState, action) {
switch(action.type) {
case GET_STOCK_LIST:
return { ...state, loadingStockList: true };
case GET_STOCK_LIST_SUCCESS:
return { ...state, loadingStockList: false, stockList: action.payload.data };
case GET_STOCK_LIST_FAIL:
return { ...state, loadingStockList: false, stockListError: 'Failed to retrieve stock list' };
case GET_STOCK:
return { ...state, loadingStock: true };
case GET_STOCK_SUCCESS:
return { ...state, loadingStock: false, stock: action.payload.data };
case GET_STOCK_FAIL:
return { ...state, loadingStock: false, stockError: 'Failed to retrieve stock list' };
case PUT_STOCK:
return { ...state, loadingStockUpdate: true };
case PUT_STOCK_SUCCESS:
return { ...state, loadingStockUpdate: false, result: action.payload.data };
case PUT_STOCK_FAIL:
return { ...state, loadingStockUpdate: false, stockUpdateError: 'Failed to update stock list' };
case GET_BARCODES:
return { ...state, loadingBarcodes: true };
case GET_BARCODES_SUCCESS:
return { ...state, loadingBarcodes: false, barcodeList: action.payload.data };
case GET_BARCODES_FAIL:
return { ...state, loadingBarcodes:false, barcodesError: 'Failed to load barcodes' };
case GET_STOCK_FROM_BARCODE:
return { ...state, loadingStockFromBarcode: true };
case GET_STOCK_FROM_BARCODE_SUCCESS:
return { ...state, loadingStockFromBarcode: false, stockFromBarcode: action.payload.data };
case GET_STOCK_FROM_BARCODE_FAIL:
return { ...state, loadingStockFromBarcode: false, stockFromBarcodeError: 'Failed to get stock item from barcode' };
default:
return state;
}
}
export function listStockArray(searchQuery, pageSize = 50, pageNumber = 1) {
return {
type: GET_STOCK_LIST,
payload: {
request: {
url: `/stock?search=${searchQuery}&pageSize=${pageSize}&pageNumber=${pageNumber}`
}
}
};
}
export function listStockItem(stockID) {
return {
type: GET_STOCK_LIST,
payload: {
request: {
url: `/stock/${stockID}`
}
}
};
}
export function updateStock(stockID, data) {
return {
type: GET_STOCK_LIST,
payload: {
request: {
url: `/stock/${stockID}`,
method: `PUT`,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
data: data,
}
}
};
}
export function listStockBarcodes(stockID) {
return {
type: GET_BARCODES,
payload: {
request: {
url: `/stock/${stockID}/barcodes`
}
}
};
}
export function listStockFromBarcode(barcode) {
return {
type: GET_BARCODES,
payload: {
request: {
url: `/stock/barcode/${barcode}`
}
}
};
}
现在我收到 header 中提到的错误: **类型错误:无法读取未定义的 属性 'map' **
这里是减速器对应用程序的实现:
import reducers from './redux/reducers/lots_reducer';
import StockList from './components/StockList';
const client = axios.create({
baseURL: 'https://api.github.com',
responseType: 'json'
});
const store = createStore(reducers, applyMiddleware(axiosMiddleware(client)));
const Stack = createStackNavigator({
StockList: {
screen: StockList
},
});
export default class App extends Component {
render() {
return (
<Provider store={store}>
<View style={styles.container}>
<Stack/>
</View>
</Provider>
);
}
}
最后是实际组件:
import { connect } from 'react-redux';
import { listStockArray } from '../redux/reducers/lots_reducer';
class StockList extends Component {
componentDidMount() {
this.props.listStockArray('panadol');
}
renderItem = ({ stockList }) => (
<TouchableOpacity
style={styles.item}
onPress={() => this.props.navigation.navigate(`Detail`, { name: stockList.StockID })}
>
<Text>{stockList.TradeName}</Text>
</TouchableOpacity>
);
render() {
const { stockList } = this.props;
return (
<FlatList
styles={styles.container}
data={stockList}
renderItem={this.renderItem}
/>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1
},
item: {
padding: 16,
borderBottomWidth: 1,
borderBottomColor: '#ccc'
}
});
const mapStateToProps = state => {
let storedRepositories = state.repos.map(repo => ({ key: (repo.id).toString(), ...repo }));
return {
repos: storedRepositories
};
};
const mapDispatchToProps = {
listStockArray
};
export default connect(mapStateToProps, mapDispatchToProps)(StockList);
对于转储的大量代码感到抱歉,它只是所有相关的,我相信错误出在某个地方有一个未定义的 initialState 但我看不到我错过了什么定义
您似乎没有定义 repos
,您想如何映射它?
const initialState = {
stockList: [],
stock: {},
result: {},
barcodeList: [],
stockFromBarcode: {},
repos: []
};
或者,您指的是另一个字段。
因为您尝试使用 map
函数来处理数组,但您 repo
不是数组。
有可能 repo
不是当你是 mapping
它(可能在赋值之前)。
Approach 我只是使用 Array.isArray()
检查它在哪里是一个数组,如果是数组,则可能 return 空数组。
正如@sagi 提到的,更好的方法是将 repo
字段初始化为空数组。基本上,这种错误发生在
you try to use array function to non-array element
这个代码
const mapStateToProps = state => {
let storedRepositories = state.repos.map(repo => ({ key: (repo.id).toString(), ...repo }));
return {
repos: storedRepositories
};
};
意味着你想要转换(将 id
更改为 key
属性)state.repos 使用 map 函数和 return 作为 repos
使用中间变量 storedRepositories
。这些部分看起来是原始的,没有从 repos 示例中更改。
出现错误是因为状态不包含 repos
数组。您还有一些其他数组处于状态(reducer 中的 initialState),但其中 none 是 repos
.
在 reducer 中,您将有效负载(获取的数据)存储在存储数组中,f.e。
case GET_STOCK_LIST_SUCCESS:
return { ...state, loadingStockList: false, stockList: action.payload.data };
将数据存储在 stockList
中。对于其他成功操作,您有其他数组名称。
组件不必使用所有存储数据,您可以只使用它感兴趣的部分 - 这是 mapStateToProps
映射的原因。您可以像
const mapStateToProps = state => {
return {
stockList: state.stockList,
stock: state.stock
};
};
这些值将以 this.props.stockList
和 this.props.stock
的形式提供。