在下面的未经测试的示例代码中,如果我想访问actions/math.js
中的Apollo GraphQL客户端实例,我必须将它从Calculator
组件传递给事件处理程序,并从WrappedCalculator
事件处理程序传递给动作创建者。在Redux动作创建器中访问Apollo GraphQL客户端的最佳方式是什么?
这会导致很多代码膨胀。
actions/math.js
动作创建者访问GraphQL客户端实例的更好方法是什么?
示例代码:
常量/ Queries.js:
const MUTATION_APPEND_TO_AUDIT_TRAIL = gql`
mutation MutationAppendToAuditTrail($mathOperation: String!, $operand1: Float!, $operand2: Float!) {
appendToAuditTrail(operation: $mathOperation, operand1: $operand1, operand2: $operand2) {
id
operation
operand1
operand2
}
}
`;
动作/ math.js:
import { INCREMENT_TOTAL_BY, MULTIPLY_TOTAL_BY } from '../constants/ActionTypes';
import { getTotal } from '../reducers';
incrementResultBy = (operand, graphQlClient) => (dispatch, getState) {
// Use selector to get the total prior to the operation.
const total = getTotal(getState());
// Send action to add a number to the total in the redux store.
dispatch({
type: types.INCREMENT_TOTAL_BY,
operand,
});
// Persist the latest user activity to the server.
graphQlClient.mutate({
mutation: MUTATION_APPEND_TO_AUDIT_TRAIL,
variables: {
mathOperation: 'ADDITION',
operand1: total,
operand2: operand,
},
});
};
multiplyResultBy = (operand, graphQlClient) => (dispatch, getState) {
// Use selector to get the total prior to the operation.
const total = getTotal(getState());
// Send action to multiply the total in the redux store by a number.
dispatch({
type: types.MULTIPLY_TOTAL_BY,
operand,
});
// Persist the latest user activity to the server.
graphQlClient.mutate({
mutation: MUTATION_APPEND_TO_AUDIT_TRAIL,
variables: {
mathOperation: 'MULTIPLICATION',
operand1: total,
operand2: operand,
},
});
};
export { incrementResultBy, multiplyResultBy };
组件/ Calculator.jsx
import React from 'react';
import ApolloClient from 'apollo-client';
const Calculator = ({
total,
operand,
onPlusButtonClick,
onMultiplyButtonClick,
}) => (
<div>
<h2>Perform operation for {total} and {operand}</h2>
<button id="ADD" onClick={onPlusButtonClick(() => this.props.operand, this.props.client)}>ADD</button><br />
<button id="MULTIPLY" onClick={() => onMultiplyButtonClick(this.props.operand, this.props.client)}>MULTIPLY</button><br />
</div>
);
DisplayPanel.propTypes = {
// Apollo GraphQL client instance.
client: React.PropTypes.instanceOf(ApolloClient),
// Props from Redux.
total: React.PropTypes.number,
operand: React.PropTypes.number,
onPlusButtonClick: React.PropTypes.func,
onMultiplyButtonClick: React.PropTypes.func,
};
export default Calculator;
容器,我已经做了传递个ApolloClient实例/ WrappedCalculator.js
import { connect } from 'react-redux';
import Calculator from '../components/Calculator';
import { incrementResultBy, multiplyResultBy } from '../actions';
import { getTotal, getOperand } from '../reducers';
const mapStateToProps = state => ({
total: getTotal(state),
operand: getOperand(state),
});
const mapDispatchToProps = dispatch => ({
onPlusButtonClick: (operand, graphQlClient) => dispatch(incrementResultBy(operand, graphQlClient)),
onMultiplyButtonClick: (operand, graphQlClient) => dispatch(multiplyResultBy(operand, graphQlClient)),
});
// Generate Apollo-aware, redux-aware higher-order container.
const WrappedCalculator = compose(
withApollo,
connect(mapStateToProps, mapDispatchToProps),
)(Calculator);
export default WrappedCalculator;
可能有点晚...但由于查询和突变是异步的,所以您需要使用thunk中间件。 Thunk中间件方便地允许您为动作创建者提供额外的arg - 所以您可以将其配置为为客户端提供额外的参数。请参阅:https://github.com/gaearon/redux-thunk#injecting-a-custom-argument – WickyNilliams