what react instalar example error reactjs redux axios redux-form

reactjs - react - redux axios request



¿Maneja solicitudes asíncronas con React, Redux y Axios? (4)

Los creadores de acciones de Redux aparentemente no admiten acciones asincrónicas, que es lo que estás tratando de hacer con la solicitud de publicación. Redux Thunk debería ayudar con esto.

Querrás un archivo store.js que tenga este aspecto:

//npm install --save redux-thunk import { createStore, applyMiddleware } from ''redux''; import thunk from ''redux-thunk''; import rootReducer from ''./reducer.js''; // Note: this API requires redux@>=3.1.0 const store = createStore( rootReducer, applyMiddleware(thunk) //needed so you can do async );

Así es como se vería su archivo de acciones. Crear se convierte en un creador de acciones que devuelve una función que luego realiza la solicitud de publicación y le permite realizar el envío allí, lo que le permite actualizar su tienda / estado. :

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); }) } }

Además, querrá pasar el método onSubmit que creó en onSubmitForm de esta manera. No estoy seguro de dónde proviene isLoading porque no lo veo importado en ese componente del contenedor, por lo que es posible que desee ver eso también:

<createOrganization onSubmitForm={this.onSubmit.bind(this)} isLoading={isLoading} />

Soy nuevo en React JS y Redux y ha sido demasiado abrumador para empezar. Estoy tratando de hacer una solicitud POST usando Axios, pero no puedo hacerlo. Puede ser que me falta algo en el archivo contenedor. Debajo está el código. Compruebe plnkr

Actualización: recibo el mensaje @@ redux-form / SET_SUBMIT_SUCCEEDED después de enviarlo. Pero cuando reviso la pestaña de red, no veo la llamada a la API. Y también cuando estoy consolando los valores enviados, solo veo valores de nombre y nombre completo. No consta de logotipo y detalles. ¿Qué me estoy perdiendo?

Archivo componente

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)

Archivo contenedor

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)


Puede hacerlo fácilmente con la ayuda de redux-saga.

Sobre redux-saga:

redux-saga es una biblioteca que tiene como objetivo hacer que los efectos secundarios de la aplicación (es decir, cosas asincrónicas como la obtención de datos y cosas impuras como acceder al caché del navegador) sean más fáciles de administrar, más eficientes de ejecutar, simples de probar y mejores para manejar fallas.

Instalación:

$ npm install --save redux-saga

o

$ yarn add redux-saga

Consulte el enlace: https://github.com/redux-saga/redux-saga


Sugeriría usar redux-promise-middleware . Esta biblioteca requiere que la acción tenga una propiedad llamada payload que es una promesa y esto es fácil con axios . Luego se integra con Redux para GET_CUSTOMERS tipo de acción raíz (por ejemplo, GET_CUSTOMERS ) con PENDING , FULFILLED y REJECTED y dispara esas acciones.

Disparar la acción es lo mismo que cualquier otra acción.

Almacenar

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);

Acción

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)); }; }

Reductor

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; } }


Sus creadores de acciones redux deben ser simples, objeto y deben despachar y actuar con un type clave obligatoria. Sin embargo, utilizando middlewares personalizados como redux-thunk , podría llamar a la solicitud axios dentro de sus creadores de acciones, ya que sin middlewares personalizados sus creadores de acciones necesitan devolver un objeto plano

Tu creador de acción se verá así

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}); }) } }

y tu reductor se verá así

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 } }

ahora mientras creas la tienda puedes hacerlo como

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

Aparte de esto, también debe configurar el formulario redux

necesita usar combineReducers y Provider para pasar a la tienda

import reducer from ''./reducer''; import { combineReducers } from ''redux''; import { reducer as formReducer } from ''redux-form'' export const rootReducer = combineReducers({ reducer, form: formReducer })

CodeSandbox