Цепная жирная стрелка в mapDispatchToProps выдает мне ошибку - PullRequest
1 голос
/ 05 июля 2019

Ошибка: действия должны быть простыми объектами. Используйте пользовательское промежуточное ПО для асинхронных действий.

Я пытаюсь объединить функции жирной стрелки в mapDispatchToProps, но, похоже, это не работает.

Создатель контейнеров и экшенов:


// Actions Creator
const inputChange = (name: string) => (
  e: React.FormEvent<HTMLInputElement>
) => ({
  type: INPUT_CHANGE,
  name,
  value: e.currentTarget.value
});

// Dispatch
const mapDispatchToProps = {
  inputChange
};

// Connect
export default connect(
  mapStateToProps,
  mapDispatchToProps
)(SignUp);

Тупой компонент

const SignUp = ({ inputChange }) => (
  <input
    type="password"
    placeholder="Password"
    onChange={inputChange('password')}
  />
);

Возможно, некоторые части этого кода кажутся немного странными, потому что я удалил часть своего types, чтобы не добавлять лишний бессмысленный код.

В любом случае ошибка исходит от mapDispatchToProps, кажется, что это нормально с единственной жирной стрелкой, но когда я начинаю их связывать, я получаю эту ошибку (даже если они возвращают объект).

Ответы [ 3 ]

2 голосов
/ 05 июля 2019

Поскольку упомянутая ошибка actions должна быть простым объектом, но когда вы объединяете функции в цепочку, вы фактически передаете function (следующий в цепочке), а не object.

Проблема здесь для вас заключается в том, что вы хотите передать дополнительный аргумент в дополнение к фактическому событию DOM, например, имя input, то есть: "пароль", "пользователь" и т. Д ...

Тогда почему бы просто не дать input имя и захватить его в функции создателя действия (так же, как вы делаете это с атрибутом value).

Ваша форма может выглядеть примерно так:

const Form = ({ inputChange, form }) => (
<div>
  <input name="user" onChange={inputChange} type="text" value={form.user} />
  <input name="password" onChange={inputChange} type="password" value={form.password} />
</div>
);

const mapState = state => ({
  form: state
});

const mapDispatch = {
  inputChange
};

const ConnectedForm = connect(
  mapState,
  mapDispatch
)(Form);

И внутри вашего создателя действия:

const inputChange = ({ target }) => ({
  type: INPUT_CHANGE,
  payload: {
    value: target.value,
    inputName: target.name
  }
});

и ваш редуктор может справиться с этим, что-то вроде этого:

const reducer = (state = {user: '', password: ''}, action) => {
  switch (action.type) {
    case INPUT_CHANGE: {
      const { inputName, value } = action.payload;
      return {
        ...state,
        [inputName]: value
      };
    }

    default:
      return state;
  }
};

Пример выполнения:

// mimic imports
const { createStore } = Redux;
const { Provider, connect } = ReactRedux;


const INPUT_CHANGE = "INPUT_CHANGE";
const reducer = (state = {user: '', password: ''}, action) => {
  switch (action.type) {
    case INPUT_CHANGE: {
      const { inputName, value } = action.payload;
      const nextState = {
        ...state,
        [inputName]: value
      };
      console.clear();
      console.log('store', nextState);
      return nextState;
    }

    default:
      return state;
  }
};

const inputChange = ({ target }) => ({
  type: INPUT_CHANGE,
  payload: {
    value: target.value,
    inputName: target.name
  }
});

const store = createStore(reducer);

const Form = ({ inputChange, form }) => (
<div>
  <input name="user" onChange={inputChange} type="text" value={form.user} />
  <input name="password" onChange={inputChange} type="password" value={form.password} />
</div>
);

const mapState = state => ({
  form: state
});

const mapDispatch = {
  inputChange
};

const ConnectedForm = connect(
  mapState,
  mapDispatch
)(Form);

class App extends React.Component {
  render() {
    return (
      <div>
        <ConnectedForm />
      </div>
    );
  }
}

const root = (
  <Provider store={store}>
    <App />
  </Provider>
);

const rootElement = document.getElementById("root");
ReactDOM.render(root, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.1/redux.min.js
"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/4.4.10/react-redux.min.js"></script>
<div id="root"/>
1 голос
/ 05 июля 2019

Вы возвращаете функцию из вашего действия, которая является неприемлемой.Отправка без промежуточного программного обеспечения принимает только плоский объект, а не функцию.

Либо используйте промежуточное программное обеспечение, такое как Thunk или saga, либо измените логику для возврата объекта, а не функционируйте, как показано ниже

ДЕЙСТВИЕ

// Actions Creator
const inputChange = (name: string, value: string) => ({
    type: INPUT_CHANGE,
    name,
    value
});

КОМПОНЕНТ

const SignUp = ({ inputChange }) => (
    <input
        type="password"
        placeholder="Password"
        onChange={(e) => inputChange('password', e.target.value)}
    />
);
1 голос
/ 05 июля 2019

Попробуйте следующий синтаксис.

const mapDispatchToProps = dispatch => {
  return {
    inputChange: () => {
      dispatch(inputChange("value"))
    }
  };
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...