редуктор

ичок в React JS и Redux, и это было слишком сложно, чтобы начать работу. Я пытаюсь сделать POST-запрос с помощью Axios, но не могу его сделать. Может быть, я что-то упустил в файле контейнера. Ниже приведен код. Проверьтеplnkr

Обновить: Я получаю сообщение @@ redux-form / SET_SUBMIT_SUCCEEDED после отправки. Но когда я проверяю на вкладке сети, я не вижу вызова API. А также, когда я утешаю представленные значения, я вижу только значения name и fullname. Он не состоит из логотипа и деталей. Чего мне не хватает?

Файл компонента

   import React, { PureComponent } from 'react'
   import PropTypes from 'prop-types'
   import { Field,reduxForm } from 'redux-form'
   import {   Columns,Column, TextArea, Label,Button  } from 'bloomer'
   import FormField from 'FormField'

   const validate = (values) => {
     const errors = {}
    const requiredFields = 
      ['organizationName','organizationFullName','organizationDetails']

    requiredFields.forEach((field) => {
     if (!values[field]) {
     errors[field] = 'This field can\'t be empty!'
    }
  })
     return errors
}

  const formConfig = {
   validate,
   form: 'createOrganization',
   enableReinitialize: true
   }

  export class CreateOrganization extends PureComponent {
   static propTypes = {
     isLoading:PropTypes.bool.isRequired,
     handleSubmit: PropTypes.func.isRequired, // from react-redux     
     submitting: PropTypes.bool.isRequired // from react-redux
    }
   onSubmit = data => {
     console.log(data)
   }
  render () {
     const { handleSubmit,submitting,isLoading } = this.props
      return (
        <Columns isCentered>
        <form onSubmit={handleSubmit(this.onSubmit.bind(this))} > 

          <Column isSize='3/6' >        
            <Label>Organization Name</Label>             
            <Field 
              name="organizationName"
              component={FormField}
              type="text"
              placeholder="Organization Name"
            />   
          </Column>       


          <Column isSize='3/6'>
            <Label>Organization Full Name</Label>              
            <Field
              name="organizationFullName"
              component={FormField}
              type="text"
              placeholder="Organization Full Name"
            />  
          </Column> 


           <Column isSize='3/6'>            
            <Label>Organization Logo</Label>              
            <Input                  
              name="organizationLogo"                  
              type="file"
              placeholder="Logo"
            /> 
          </Column>

          <Column isSize='3/6'>
            <Label>Organization Details</Label>         
                <TextArea placeholder={'Enter Details'} />               
          </Column>          


          <Column >
            <span className="create-button">
              <Button type="submit" isLoading={submitting || isLoading} isColor='primary'>
                Submit
              </Button>  
            </span> 
              <Button type="button" isColor='danger'>
                Cancel
              </Button>                
          </Column>  

        </form>
      </Columns>
    )    
  }
}

  export default reduxForm(formConfig)(CreateOrganization)

Контейнерный файл

   import React, { PureComponent } from 'react'
   import PropTypes from 'prop-types'
   import { connect } from 'react-redux'
   import Loader from 'Loader'
   import organization from 'state/organization'
   import CreateOrganization from '../components/createOrganization'

   export class Create extends PureComponent {
   static propTypes = {    
     error: PropTypes.object,
     isLoaded: PropTypes.bool.isRequired,  
     create: PropTypes.func.isRequired,   
    }
    onSubmit = data => {
      this.props.create(data)
    }

    render () {
      const { isLoaded, error } = this.props
    return (      
       <CreateOrganization onSubmitForm={this.onSubmit} isLoading=
         {isLoading} />    
     )
   }
 }

   const mapStateToProps = state => ({
     error: organization.selectors.getError(state),
     isLoading: organization.selectors.isLoading(state)
   })

    const mapDispatchToProps = {
      create: organization.actions.create
    }


  export default connect(mapStateToProps, mapDispatchToProps)(Create)
 Joshua Underwood28 нояб. 2017 г., 23:01
onSubmit должен указывать на функцию объекта props.
 HebleV28 нояб. 2017 г., 22:46
Я не могу войти в функцию вызова API. Спасибо за ваше предложение. Добавим изменения
 Joshua Underwood28 нояб. 2017 г., 22:38
постскриптум<CreateOrg onSubmit={this.props} /> this.props это объектне функция
 HebleV28 нояб. 2017 г., 23:11
И эта функция будет объявлена ​​в действии?
 Joshua Underwood28 нояб. 2017 г., 22:37
Перво-наперво, люди начнут голосовать по этому вопросу просто потому, что форматирование ужасное. Это затрудняет чтение. Вы можете опубликовать пример кода, если вы не можете получить правильное форматирование здесь. Во-вторых, вы должны быть более наглядными в том, что вам нужно. Что не работает? Вы можете войти в функцию callAPI? Не получен ли в консоли ответ?

Ответы на вопрос(4)

очевидно, не поддерживают асинхронные действия, что вы пытаетесь сделать с пост-запросом. Redux Thunk должен помочь с этим.

Вам понадобится файл store.js, который выглядит следующим образом:

//npm install --save redux-thunk

import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducer.js';

// Note: this API requires [email protected]>=3.1.0
const store = createStore(
  rootReducer,
  applyMiddleware(thunk) //needed so you can do async
);

Вот как будет выглядеть ваш файл действий. Create становится создателем действия, который возвращает функцию, которая затем выполняет запрос post и позволяет вам отправлять туда информацию, позволяя обновить ваш магазин / состояние. :

import axios from 'axios'
import { CREATE_ORGANIZATION, CREATE_ORGANIZATION_SUCCESS, CREATE_ORGANIZATION_FAILURE,

       } from './constants'
import * as selectors from './selectors'

/*
  CREATE ORGANIZATION
*/
//uses redux-thunk to make the post call happen
export function create (values) {
  return function(dispatch) {
    return axios.post('/url', values).then((response) => {
      dispatch({ type: 'Insert-constant-here'})
      console.log(response);
    })
    }
  }

Кроме того, вы захотите передать метод onSubmit, который вы создали, в onSubmitForm следующим образом. Я не уверен, откуда исходит isLoading, потому что я не вижу его импортированным в этом компоненте контейнера, так что вы можете посмотреть на это тоже:

  <createOrganization onSubmitForm={this.onSubmit.bind(this)} isLoading={isLoading} />
 HebleV01 дек. 2017 г., 07:55
Мой файл контейнера правильный?
 Dream_Cap01 дек. 2017 г., 07:49
Да, введите в действие типа там.
 HebleV01 дек. 2017 г., 07:38
Является ли «Insert-constant-here» типом действия, например CREATE_ORGANIZATION_SUCCESS для ex?
 HebleV01 дек. 2017 г., 07:55
Я все еще получаю '@@ redux-form / SET_SUBMIT_FAILED' в консоли
 Dream_Cap01 дек. 2017 г., 08:03
Я обновил свой ответ. Я думаю, вы захотите внести некоторые изменения там
Решение Вопроса

объектными и должны отправлять и действовать с обязательным ключомtype, Однако с использованием пользовательских промежуточных программ, таких какredux-thunk ты можешь позвонитьaxios Запрашивайте в ваших действиях создателей как без кастомовmiddlewares создатели ваших действий должны вернуть простой объект

Ваш создатель действий будет выглядеть

export function create (values) {

  return (dispatch) => {
     dispatch({type: CREATE_ORGANIZATION});
     axios.post('/url', values)   
        .then((res) =>{
            dispatch({type: CREATE_ORGANIZATION_SUCCESS, payload: res});
        })
        .catch((error)=> {
            dispatch({type: CREATE_ORGANIZATION_FAILURE, payload: error});
        })
  }

}

и ваш редуктор будет выглядеть

export default (state = initialState, action) => {
  const payload = action.payload

   switch (action.type) {    
    case CREATE:    

      return {
        ...state,
        loading: true,
        loaded: false
      }

    case CREATE_SUCCESS:
      return {
        ...state,
        data: state.data.concat(payload.data),
        loading: false,
        loaded: true,
        error: null
      }   

      }

    case CREATE_FAILURE:

      return {
        ...state,
        loading: false,
        loaded: true,
        error: payload
      }
    default:
      return state
  }
}

Теперь при создании магазина вы можете сделать это как

import thunk from 'redux-thunk';
import { createStore, applyMiddleware } from 'redux';
const store = createStore(
  reducer,
  applyMiddleware(thunk)
);

Помимо этого вам также нужно настроить форму приставки

вам нужно использовать объединение и провайдера для передачи в магазин

import reducer from './reducer';
import { combineReducers } from 'redux';
import { reducer as formReducer } from 'redux-form'

export const rootReducer = combineReducers({
   reducer,
   form: formReducer
})

CodeSandbox

 Evhz01 дек. 2017 г., 11:14
похоже, ваша конфигурация не позволяет redux-thunk отправлять действие, которое запускает ваш запрос API. Проверьте своиapplyMiddleware( your_middleware?, thunk, logger)(createStore) Затем попробуйте реализовать логику без использованияredux-form
 HebleV01 дек. 2017 г., 08:40
Посмотрим. Спасибо
 Shubham Khatri01 дек. 2017 г., 08:08
проверьте этот ответ и дайте мне знать, если у вас возникнут трудности
 HebleV01 дек. 2017 г., 08:24
Я все еще получаю '@@ redux-form / SET_SUBMIT_FAILED' в консоли
 Shubham Khatri01 дек. 2017 г., 08:39
Я добавил codeSandbox со всеми исправлениями ошибок, вам нужно было использовать combReducers и настроить в нем избыточную форму. Помимо этого были и другие ошибки, такие как не использование символов верхнего регистра для компонента. Дайте мне знать, если вы все еще сталкиваетесь с проблемами

перевождите-обещание-промежуточный слой, Эта библиотека требует, чтобы у действия было свойство с именемpayload этообещание и это легко сaxios, Затем он интегрируется сRedux добавить суффикс к корневому типу действия (например,GET_CUSTOMERS) с участиемPENDING, FULFILLED, а такжеREJECTED и запускает эти действия.

Стрельба в действии такая же, как и в любом другом действии.

хранить
import {applyMiddleware, compose, createStore} from 'redux';
import promiseMiddleware from 'redux-promise-middleware';
import reducer from './reducers';

let middleware = applyMiddleware(promiseMiddleware());
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const enhancer = composeEnhancers(middleware);

export default createStore(reducer, enhancer);
действие
export function getCustomers() {
  return {
    type: 'GET_CUSTOMERS',
    payload: axios.get('url/to/api')
      .then(res => {
        if (!res.ok) throw new Error('An error occurred.');
        return res;
      })
      .then(res => res.json())
      .catch(err => console.warn(err));
  };
}
редуктор
export default function(state = initialState, action) => {
  switch (action.type) {
    case 'GET_CUSTOMERS_PENDING':
      // this means the call is pending in the browser and has not
      // yet returned a response
      ...
    case 'GET_CUSTOMERS_FULFILLED':
      // this means the call is successful and the response has been set
      // to action.payload
      ...
    case 'GET_CUSTOMERS_REJECTED':
      // this means the response was unsuccessful so you can handle that
      // error here
      ...
    default:
      return state;
  }
}

О редукс-саге:

redux-saga это библиотека, которая призвана сделать побочные эффекты приложения (то есть асинхронные вещи, такие как выборка данных и нечистые вещи, такие как доступ к кешу браузера) более легкими в управлении, более эффективными для выполнения, простыми для тестирования и лучше справляться с ошибками.

Монтаж:
$ npm install --save redux-saga 

или же

$ yarn add redux-saga

Пожалуйста, обратитесь к ссылке:https://github.com/redux-saga/redux-saga

Ваш ответ на вопрос