Как обрабатывать диспетчеризацию действий для вложенного компонента React Redux - PullRequest
3 голосов
/ 09 июля 2020

Я делаю что-то подобное для своего компонента пользовательского интерфейса в приложении React Redux:

// Outer.js
import Inner from './path'

export const Outer = () => {
    return (
        <div>
            ...
            <Inner />
            ...
        </div>
    )
}
// Inner.js
const param = ''
export const Inner = () => {
    return (
        <div>
            <TextField 
                input={param}
                onChange = {(param) => {
                    Function(param)
                }}
            />
        </div>
    )
}

Я также настроил компонент контейнера для Outer. js:

// OuterContainer.js
import Outer from './path'

const mapStateToProps = (state) => {
    paramToBeUpdated: ???
}

const mapDispatchToProps = (dispatch) => {
    Function: (param) => dispatch(Function(param))
}

export default connect(mapStateToProps, mapDispatchToProps)(Outer)

Мое действие создано для этого шага:

action/index.js
export const Function = (param) => (dispatch, getState) => {
    dispatch({ type: 'FUNCTION', param })
}

И мой редуктор включал следующую функцию:

// reducer.js
export default reducer = (state="", action) => {
    switch(action.type) {
        case 'FUNCTION':
            return {
                ...state,
                param: action.param
            }
        ...
    }
}

Я пытаюсь обновить переменную paramToBeUpdated ' s значение из внутреннего компонента пользовательского интерфейса. Но это не сработало.

Могут ли компоненты Inner и Outer совместно использовать компонент-контейнер, связанный с Outer?

Как мне сделать это, не внося слишком много изменений в мои текущая настройка? Можно ли избежать создания нового внутреннего контейнера, который по сути будет копией внешнего контейнера?

Ответы [ 2 ]

2 голосов
/ 09 июля 2020

Если вы не можете связать Inner со значением состояния и / или действием, значит, вы сделали что-то не так, вот рабочий пример:

const { Provider, connect } = ReactRedux;
const { createStore, applyMiddleware, compose } = Redux;
const { produce } = immer;

const initialState = {
  value: '',
};
//action types
const CHANGE = 'CHANGE';
//action creators

const change = (value) => ({
  type: CHANGE,
  payload: value,
});
const reducer = (state, { type, payload }) => {
  if (type === CHANGE) {
    return produce(state, (draft) => {
      draft.value = payload;
    });
  }
  return state;
};
//creating store with redux dev tools
const composeEnhancers =
  window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(
  reducer,
  initialState,
  composeEnhancers(
    applyMiddleware(() => (next) => (action) =>
      next(action)
    )
  )
);
//components
const Inner = connect((state) => state.value, {
  Function: change,
})(({ Function, value }) => {
  return (
    <input
      type="text"
      value={value}
      onChange={(e) => Function(e.target.value)}
    />
  );
});

const Outer = () => {
  return (
    <div>
      <Inner />
    </div>
  );
};
ReactDOM.render(
  <Provider store={store}>
    <Outer />
  </Provider>,
  document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js"></script>
<script src="https://unpkg.com/immer@7.0.5/dist/immer.umd.production.min.js"></script>
<div id="root"></div>
0 голосов
/ 09 июля 2020

Только Outer подключен к магазину redux. Если вы хотите отправить действие из Inner, вы можете сделать:

  1. Подключить Inner к хранилищу redux
// Inner.js
const Inner = (props) => {
    return (
        <div>
            <TextField 
                input={param}
                onChange = {(param) => {
                    props.Function(param)
                }}
            />
        </div>
    )
}
export default connect(null, mapDispatchToProps)(Inner)

не нужно создавать никаких InnerContainer

Передать функцию отправки из Outer (+ контейнер не нужен)
// Outer.js
import Inner from './path'

export const Outer = (props) => {
    return (
        <div>
            ...
            <Inner Function={props.Function} />
            ...
        </div>
    )
}

const mapStateToProps = (state) => {
    paramToBeUpdated: ???
}

const mapStateToProps = (dispatch) => {
    Function: (param) => dispatch(Function(param))
}

export default connect(mapStateToProps, mapDispatchToProps)(Outer)
// Inner.js
const Inner = (props) => {
    return (
        <div>
            <TextField 
                input={param}
                onChange = {(param) => {
                    props.Function(param)
                }}
            />
        </div>
    )
}
...