Làm thế nào để truy cập trạng thái bên trong bộ giảm tốc Redux?


86

Tôi có một bộ giảm tốc và để tính toán trạng thái mới, tôi cần dữ liệu từ hành động và cả dữ liệu từ một phần của trạng thái không được bộ giảm tốc này quản lý. Cụ thể, trong phần giảm thiểu tôi sẽ hiển thị bên dưới, tôi cần truy cập vào accountDetails.stateOfResidenceIdtrường.

InitialState.js:

export default {
    accountDetails: {
        stateOfResidenceId: '',
        accountType: '',
        accountNumber: '',
        product: ''
    },
    forms: {
        blueprints: [

        ]
    }
};

formReducer.js:

import * as types from '../constants/actionTypes';
import objectAssign from 'object-assign';
import initialState from './initialState';
import formsHelper from '../utils/FormsHelper';
export default function formsReducer(state = initialState.forms, action) {
  switch (action.type) {
    case types.UPDATE_PRODUCT: {
        //I NEED accountDetails.stateOfResidenceId HERE
        console.log(state);
        const formBlueprints = formsHelper.getFormsByProductId(action.product.id);
        return objectAssign({}, state, {blueprints: formBlueprints});
    }

    default:
      return state;
  }
}

index.js (trình giảm thiểu gốc):

import { combineReducers } from 'redux';
import accountDetails from './accountDetailsReducer';
import forms from './formsReducer';

const rootReducer = combineReducers({
    accountDetails,
    forms
});

export default rootReducer;

Tôi có thể truy cập trường này bằng cách nào?



8
Câu nói đó không có ý nghĩa gì cả. Toàn bộ điểm của chức năng giảm tốc là bạn đưa ra quyết định dựa trên trạng thái hiện tại và hành động.
markerikson,

Câu trả lời:


105

Tôi sẽ sử dụng thunk cho điều này, đây là một ví dụ:

export function updateProduct(product) {
  return (dispatch, getState) => {
    const { accountDetails } = getState();

    dispatch({
      type: UPDATE_PRODUCT,
      stateOfResidenceId: accountDetails.stateOfResidenceId,
      product,
    });
  };
}

Về cơ bản, bạn nhận được tất cả dữ liệu bạn cần cho hành động, sau đó bạn có thể gửi dữ liệu đó đến trình giảm thiểu của mình.


4
Bất kỳ ý tưởng nào tại sao trạng thái hiện tại không được REDUX tiếp xúc với bộ giảm tốc ..? có vẻ kỳ lạ rằng khi cử tôi cần phải thêm những thứ không liên quan đến giảm tốc chỉ để tình trạng ban đầu sẽ không ghi đè lên tình trạng hiện thời của công cụ liên quan khác để gọi văn hiện nay
vsync

10

Các tùy chọn của bạn là viết nhiều logic hơn ngoài việc chỉ sử dụng combineReducershoặc bao gồm nhiều dữ liệu hơn trong hành động. Câu hỏi thường gặp về Redux bao gồm chủ đề này:

https://redux.js.org/faq/reducers/

Ngoài ra, tôi hiện đang làm việc trên một tập hợp các trang mới của tài liệu Redux về chủ đề "Bộ giảm cấu trúc", mà bạn có thể thấy hữu ích. Các trang WIP hiện tại có tại https://github.com/markerikson/redux/blob/struct-reducers-page/docs/recipes/StructuringReducers.md .


Cảm ơn câu trả lời của bạn. Tôi đã khám phá một số tài nguyên mà bạn đã liên kết và sẽ tiếp tục làm như vậy. Tuy nhiên, câu hỏi cho bạn, vì bạn có vẻ là người hiểu biết. Một câu trả lời khác đề xuất việc sử dụng thunk. Bạn có nghĩ rằng đây sẽ là một giải pháp tốt cho vấn đề của tôi? Nếu nó làm cho mã của tôi trở nên lộn xộn hoặc không phải là phương pháp hay nhất thì đó không phải là giải pháp tôi muốn theo đuổi, nhưng tôi cảm thấy không đủ hiểu biết để xác định ảnh hưởng lâu dài của những lựa chọn này.
twilco

3
Yup, côn là cách tiếp cận cơ bản tiêu chuẩn để quản lý các tác dụng phụ và thực hiện logic phức tạp liên quan đến nhiều lần gửi và sử dụng trạng thái ứng dụng hiện tại. Hoàn toàn bình thường khi viết một hàm thunk để đọc trạng thái ứng dụng hiện tại và thực hiện những việc như gửi đi có điều kiện, gửi nhiều hành động hoặc lấy một phần của trạng thái và bao gồm điều đó trong một hành động đã gửi. Tôi có một số ví dụ về các mẫu thunk phổ biến tại gist.github.com/markerikson/ea4d0a6ce56ee479fe8b356e099f857e .
markerikson

2

Tôi không chắc liệu cách tiếp cận này có phải là một mô hình chống nhưng nó đã hiệu quả với tôi. Sử dụng một hàm curry trong các hành động của bạn.

export const myAction = (actionData) => (dispatch, getState) => {
   dispatch({
      type: 'SOME_ACTION_TYPE',
      data: actionData,
      state: getState()
   });
}

1

Thật đơn giản để viết hàm kết hợp của riêng bạn thực hiện chính xác những gì bạn muốn:

import accountDetails from './accountDetailsReducer';
import forms from './formsReducer';

const rootReducer = (state, action) => {
        const newState = {};

        newState.accountDetails = accountDetails(state.accountDetails, action);
        newState.forms = forms(state.forms, action, state.accountDetails);

        return newState;
    };

export default rootReducer; 

FormReducer của bạn sau đó sẽ là:

export default function formsReducer(state = initialState.forms, action, accountDetails) {

FormReducer hiện có quyền truy cập vào accountDetails.

Lợi ích của cách tiếp cận này là bạn chỉ hiển thị các phần của trạng thái mà bạn cần, thay vì toàn bộ trạng thái.


0

Tôi khuyên bạn nên chuyển nó vào trình tạo hành động. Vì vậy, ở một nơi nào đó, bạn sẽ có một người tạo hành động làm những việc như sau:

updateProduct(arg1, arg2, stateOfResidenceId) {
  return {
    type: UPDATE_PRODUCT,
    stateOfResidenceId
  }
}

Tại nơi bạn kích hoạt hành động, giả sử bạn đang sử dụng phản ứng, bạn có thể sử dụng

function mapStateToProps(state, ownProps) {
  return {
    stateOfResidenceId: state.accountdetails.stateOfResidenceId
  }  
}

và kết nối với thành phần phản ứng của bạn bằng cách sử dụng kết nối của react-redux.

connect(mapStateToProps)(YourReactComponent);

Bây giờ, trong thành phần phản ứng của bạn nơi bạn kích hoạt sản phẩm cập nhật hành động, bạn sẽ có stateOfResidenceId làm chỗ dựa và bạn có thể chuyển nó cho người tạo hành động của mình.

Nghe có vẻ phức tạp, nhưng nó thực sự là về sự tách biệt các mối quan tâm.


0

Bạn có thể thử sử dụng:

redux-tên-giảm

Điều này cho phép bạn có được trạng thái ở bất kỳ đâu trong mã của mình như sau:

const localState1 = getState(reducerA.state1)
const localState2 = getState(reducerB.state2)

Nhưng trước hết hãy nghĩ nếu chuyển trạng thái bên ngoài làm trọng tải trong hành động sẽ tốt hơn.


0

Một cách khác, nếu bạn sử dụng react-redux và chỉ cần hành động đó ở một nơi HOẶC có thể tạo HOC (Thành phần oder cao hơn, không thực sự cần hiểu rằng điều quan trọng là điều này có thể làm phồng html của bạn) ở mọi nơi bạn cần quyền truy cập đó là sử dụng các bước hợp nhất với các tham số bổ sung được chuyển cho hành động:

const mapState = ({accountDetails: {stateOfResidenceId}}) => stateOfResidenceId;

const mapDispatch = (dispatch) => ({
  pureUpdateProduct: (stateOfResidenceId) => dispatch({ type: types.UPDATE_PRODUCT, payload: stateOfResidenceId })
});

const mergeProps = (stateOfResidenceId, { pureUpdateProduct}) => ({hydratedUpdateProduct: () => pureUpdateProduct(stateOfResidenceId )});

const addHydratedUpdateProduct = connect(mapState, mapDispatch, mergeProps)

export default addHydratedUpdateProduct(ReactComponent);

export const OtherHydratedComponent = addHydratedUpdateProduct(OtherComponent)

Khi bạn sử dụng mergeProps, những gì bạn trả về sẽ được thêm vào props, mapState và mapDispatch sẽ chỉ dùng để cung cấp các đối số cho mergeProps. Vì vậy, nói cách khác, hàm này sẽ thêm điều này vào các đạo cụ thành phần của bạn (cú pháp kiểu chữ):

{hydratedUpdateProduct: () => void}

(lưu ý rằng hàm thực sự trả về chính hành động chứ không phải vô hiệu, nhưng bạn sẽ bỏ qua điều đó trong hầu hết các trường hợp).

Nhưng những gì bạn có thể làm là:

const mapState = ({ accountDetails }) => accountDetails;

const mapDispatch = (dispatch) => ({
  pureUpdateProduct: (stateOfResidenceId) => dispatch({ type: types.UPDATE_PRODUCT, payload: stateOfResidenceId })
  otherAction: (param) => dispatch(otherAction(param))
});

const mergeProps = ({ stateOfResidenceId, ...passAlong }, { pureUpdateProduct, ... otherActions}) => ({
  ...passAlong,
  ...otherActions,
  hydratedUpdateProduct: () => pureUpdateProduct(stateOfResidenceId ),
});

const reduxPropsIncludingHydratedAction= connect(mapState, mapDispatch, mergeProps)

export default reduxPropsIncludingHydratedAction(ReactComponent);

điều này sẽ cung cấp những thứ sau cho đạo cụ:

{
  hydratedUpdateProduct: () => void,
  otherAction: (param) => void,
  accountType: string,
  accountNumber: string,
  product: string,
}

Nhìn chung, mặc dù hoàn toàn không tán thành, những người bảo trì redux cho thấy việc mở rộng chức năng của gói của họ để bao gồm những mong muốn như vậy theo cách tốt, điều này sẽ tạo ra một khuôn mẫu cho các chức năng này mà KHÔNG hỗ trợ sự phân mảnh của hệ sinh thái, là điều rất ấn tượng.

Các gói như Vuex không quá cứng đầu gần như không có quá nhiều vấn đề với những người lạm dụng phản vật chất vì chúng bị thất lạc, đồng thời hỗ trợ một cách thức rõ ràng hơn với ít bản soạn sẵn hơn so với những gì bạn sẽ lưu trữ bằng redux và các gói hỗ trợ tốt nhất. Và mặc dù gói phần mềm này linh hoạt hơn, nhưng documantation vẫn dễ hiểu hơn vì chúng không bị lạc vào các chi tiết như tài liệu reduxs thường làm.


-1

Trong khi gửi một hành động, bạn có thể chuyển một tham số. Trong trường hợp này, bạn có thể chuyển accountDetails.stateOfResidenceIdcho hành động và sau đó chuyển cho bộ giảm tốc dưới dạng tải trọng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.