Flutter and Redux



我写了一个应用程序,使用Redux来管理我的状态。我不知道为什么,但当我启动我的应用程序时,我的控制台会向我抛出这种类型的错误:

The getter 'length' was called on null.
Receiver: null
Tried calling: length

我只是一个使用redux的初学者,所以如果这只是一个小而有趣的错误,请原谅:(

我粘贴以下代码:order_screen.dart

class OrdersScreen extends StatelessWidget{
void handleInitialBuild(OrdersScreenProps props){
props.getOrders();
}
@override
Widget build(BuildContext context){
return StoreConnector<AppState, OrdersScreenProps>(
converter: (store) => mapStateToProps(store),
onInitialBuild: (props) => this.handleInitialBuild(props),
builder: (context, props){
List<Order> data = props.listResponse.data;
bool loading = props.listResponse.loading;
Widget body;
if(loading){
body = Center(
child: CircularProgressIndicator(),
);
}else{
body = ListView.separated(
padding: const EdgeInsets.all(16.0),
itemCount: data.length,
separatorBuilder: (context, index) => Divider(),
itemBuilder: (context, i) {
Order order = data[i];
return ListTile(
title: Text(
order.title,
),
onTap: () {
props.getOrderDetails(order.id);
Navigator.pushNamed(context, AppRoutes.orderDetails);
},
);
},
);
}
return Scaffold(
appBar: AppBar(
title: Text('Orders list'),
),
body: body,
);
},
);
}
}
class OrdersScreenProps {
final Function getOrders;
final Function getOrderDetails;
final ListOrdersState listResponse;
OrdersScreenProps({
this.getOrders,
this.listResponse,
this.getOrderDetails,
});
}
OrdersScreenProps mapStateToProps(Store<AppState> store) {
return OrdersScreenProps(
listResponse: store.state.order.list,
getOrders: () => store.dispatch(getOrders()),
getOrderDetails: (int id) => store.dispatch(getOrderDetails(id)),
);
}

order_actions.dart

const LIST_ORDERS_REQUEST = 'LIST_ORDERS_REQUEST';
const LIST_ORDERS_SUCCESS = 'LIST_ORDERS_SUCCESS';
const LIST_ORDERS_FAILURE = 'LIST_ORDERS_FAILURE';
RSAA getOrdersRequest(){
return RSAA(
method: 'GET',
endpoint: 'http://10.0.2.2:80/order',
types: [
LIST_ORDERS_FAILURE,
LIST_ORDERS_REQUEST,
LIST_ORDERS_SUCCESS
],
headers: {
'Content-Type':'application/json',
},
);
}
ThunkAction<AppState> getOrders() => (Store<AppState> store) => store.dispatch(getOrdersRequest());
const GET_ORDERS_DETAILS_REQUEST = 'GET_ORDERS_DETAILS_REQUEST';
const GET_ORDERS_DETAILS_SUCCESS = 'GET_ORDERS_DETAILS_SUCCESS';
const GET_ORDERS_DETAILS_FAILURE = 'GET_ORDERS_DETAILS_FAILURE';
RSAA getOrderDetailsRequest(int id){
return RSAA(
method: 'GET',
endpoint: 'http://10.0.2.2:80/order/$id',
types: [
GET_ORDERS_DETAILS_REQUEST,
GET_ORDERS_DETAILS_SUCCESS,
GET_ORDERS_DETAILS_FAILURE
],
headers: {
'Content-Type':'application-type',
},
);
}
ThunkAction<AppState> getOrderDetails(int id) => (Store<AppState> store) => store.dispatch(getOrderDetailsRequest(id));

order_state.dart

class OrderState{
ListOrdersState list;
OrderDetailsState details;
OrderState({
this.list,
this.details,
});
factory OrderState.initial() => OrderState(
list: ListOrdersState.initial(),
details: OrderDetailsState.initial(),
);
}
class ListOrdersState {
dynamic error;
bool loading;
List<Order> data;
ListOrdersState({
this.error,
this.loading,
this.data,
});
factory ListOrdersState.initial() => ListOrdersState(
error: null,
loading: false,
data: [],
);
}
class OrderDetailsState {
dynamic error;
bool loading;
OrderDetails data;
OrderDetailsState({
this.error,
this.loading,
this.data,
});
factory OrderDetailsState.initial() => OrderDetailsState(
error: null,
loading: false,
data: null,
);
}

app_state.dart

@immutable
class AppState {
final UserState user;
final OrderState order;
AppState({
this.user,
this.order
});
factory AppState.initial() => AppState(
user: UserState.initial(),
order: OrderState.initial()
);
AppState copyWith({
UserState user,
OrderState order,
}) {
return AppState(
user: user ?? this.user,
order: order ?? this.order,
);
}

order_reducer.dart

OrderState orderResucer(OrderState state, FSA action){
OrderState newState = state;
switch (action.type) {
case LIST_ORDERS_REQUEST:
newState.list.error = null;
newState.list.loading = true;
newState.list.data = null;
return newState;
case LIST_ORDERS_SUCCESS:
newState.list.error = null;
newState.list.loading = false;
newState.list.data = ordersFromJSONStr(action.payload);
return newState;
case LIST_ORDERS_FAILURE:
newState.list.error = action.payload;
newState.list.loading = false;
newState.list.data = null;
return newState;

case GET_ORDERS_DETAILS_REQUEST:
newState.details.error = null;
newState.details.loading = true;
newState.details.data = null;
return newState;
case GET_ORDERS_DETAILS_SUCCESS:
newState.details.error = null;
newState.details.loading = false;
newState.details.data = orderFromJSONStr(action.payload);
return newState;
case GET_ORDERS_DETAILS_FAILURE:
newState.details.error = action.payload;
newState.details.loading = false;
newState.details.data = null;
return newState;
default:
return newState;
}
}
List<Order> ordersFromJSONStr(dynamic payload) {
Iterable jsonArray = json.decode(payload);
return jsonArray.map((j) => Order.fromJSON(j)).toList();
}
OrderDetails orderFromJSONStr(dynamic payload) {
return OrderDetails.fromJSON(json.decode(payload));
}

首先需要对reducer执行操作,并调用要更改的状态的相关操作。

TypedReducer<OrderState, FSA>(orderReducer>); //pass it your reducers in store

触发相关动作

ThunkAction<AppState> getOrders() => (Store<AppState> store) ={
store.dispatch(FSA(type: LIST_ORDERS_REQUEST);
store.dispatch(getOrdersRequest().then((orders){
store.dispatch(FSA(type: LIST_ORDERS_REQUEST);
}), onError(e){
store.dispatch(FSA(type: LIST_ORDERS_FAILURE);
}
};

您的getOrders((应该返回future。制作ThunkAction的全部目的是返回一个函数,一旦其中的异步函数完成,该函数就会调度常规同步操作。

最新更新