Así que estoy tratando de aprender Reaccionar con Redux y hasta ahora creo que he podido resolver la mayoría del código necesario para que funcione, pero tengo un problema para que mi estado pase a mi componente. Estoy usando la plantilla de proyecto ASP.NET Core de Visual Studio 2017 que tiene códigos de reacción y redux boilerplate y usaron esto:

export default connect(
  state => state.weatherForecasts,
  dispatch => bindActionCreators(actionCreators, dispatch)
)(FetchData);

Intenté hacer lo mismo con mi propio componente así:

export default connect(
  state => state.lecture,
  dispatch => bindActionCreators(actionCreators, dispatch)
)(LectureTable);

Pero cuando intento acceder al contenido de mis accesorios, las propiedades que quiero obtener se etiquetan como indefinidas. Verifiqué a través de Devux de Redux que mi estado inicial existe, pero mi componente no puede ver los accesorios que estoy tratando de pasarle. Lo extraño es que acabo de imitar el código repetitivo, pero aún no funciona, el código repetitivo funciona bien (es decir, puedo ir al componente y cerrar sesión en su estado inicial).

Como sigo el formato utilizado por Visual Studio, mis creadores de acción, reductores y constantes están en un archivo que se muestra a continuación:

const GET_LECTURES = "GET_LECTURES";

const initialState = {
    lectures: [],
    selectedLecture: {},
    isLoading: false,
    test: 0
};

export const actionCreators = {
    requestLectures: isLoading => async (dispatch) => 
    {    
      if (!isLoading) {
        // Don't issue a duplicate request (we already have or are loading the requested data)
        return;
      }

      dispatch({ type: GET_LECTURES });

      const url = `api/lecture/`;
      const response = await fetch(url);
      const lectures = await response.json();

      dispatch({ type: RECEIVE_LECTURES, payload: lectures });
    } 
  };

export const reducer = (state = initialState, action) => {
    switch (action.type) {
    case GET_LECTURES:
        return { ...state, isLoading: true }; 
        default:
        return state;
    }
};

Lo siento si todo es desordenado. Realmente estoy empezando a comenzar a entender redux ..

Editar Mi código de componente:

import React, { Component } from 'react';
import {Button, Table, Label, Menu, Icon} from 'semantic-ui-react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import {actionCreators} from './../../store/Lecture';

export class LectureTable extends Component {

  componentWillMount(){
   // this.props.requestLectures(this.props.isLoading);
    console.log(this.props.test);
  }

  render() {
    return (
        <Table size='large'>
        {/*removed to make it cleaner..currently only has static data too lol*/}
      </Table>
    )
  }
}



export default connect(
  state => state.lecture,
  dispatch => bindActionCreators(actionCreators, dispatch)
)(LectureTable);

Donde está configurada mi tienda:

import { applyMiddleware, combineReducers, compose, createStore } from 'redux';
import thunk from 'redux-thunk';
import { routerReducer, routerMiddleware } from 'react-router-redux';
import * as Lecture from './Lecture';
import * as Counter from './Counter';
import * as WeatherForecasts from './WeatherForecasts';

export default function configureStore(history, initialState) {
  const reducers = {
    lecture: Lecture.reducer,
    counter: Counter.reducer,
    weatherForecasts: WeatherForecasts.reducer
  };

  const middleware = [
    thunk,
    routerMiddleware(history)
  ];

  // In development, use the browser's Redux dev tools extension if installed
  const enhancers = [];
  const isDevelopment = process.env.NODE_ENV === 'development';
  if (isDevelopment && typeof window !== 'undefined' && window.devToolsExtension) {
    enhancers.push(window.devToolsExtension());
  }

  const rootReducer = combineReducers({
    ...reducers,
    routing: routerReducer
  });

  return createStore(
    rootReducer,
    initialState,
    compose(applyMiddleware(...middleware), ...enhancers)
  );
}

My index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { ConnectedRouter } from 'react-router-redux';
import { createBrowserHistory } from 'history';
import configureStore from './store/configureStore';
import App from './pages/App';
import registerServiceWorker from './registerServiceWorker';

// Create browser history to use in the Redux store
const baseUrl = document.getElementsByTagName('base')[0].getAttribute('href');
const history = createBrowserHistory({ basename: baseUrl });

// Get the application-wide store instance, prepopulating with state from the server where available.
const initialState = window.initialReduxState;
const store = configureStore(history, initialState);

const rootElement = document.getElementById('root');

ReactDOM.render(
  <Provider store={store}>
    <ConnectedRouter history={history}>
      <App />
    </ConnectedRouter>
  </Provider>,
  rootElement);

registerServiceWorker();
2
kobowo 9 sep. 2018 a las 22:55

5 respuestas

La mejor respuesta

Encontré la solución. En primer lugar, soy un novato tanto para stackoverflow como para reaccionar, así que pido disculpas por todas mis inconsistencias (si ese es el término correcto).

Lo que descubrí:

  1. Estoy usando react router
  2. Estaba haciendo el método de conexión a un subcomponente del componente que representa el enrutador
  3. Coloqué el método de conexión al componente principal y funcionó

Algunas notas:

  • state => state.lecture todavía funciona
  • Tomaré en serio todos sus consejos y cambiaré mi código en consecuencia
  • La única razón por la que me empeñé en resolver el problema usando el código que tenía fue porque no podía aceptar el hecho de que el código repetitivo no funcionaría a menos que hubiera hecho algo específicamente diferente de lo que hizo el repetitivo. Simplemente no tomé en cuenta que el enrutador jugó un papel muy importante con él.
  • Repito ... soy un novato de reacción, así que lo siento por perder su tiempo T_T

Editar de nuevo: Pude conectar un componente hijo diferente con la tienda Redux. Estoy tratando de ver por qué todavía no puedo hacerlo para ese componente específico que me hizo hacer esta pregunta. Actualizaré mi respuesta una vez que encuentre la razón.

1
kobowo 12 sep. 2018 a las 15:21

El primer argumento para connect ( ) debería ser una función que devuelva un objeto, con los accesorios que desea agregar como claves, y su valor es el valor del estado. p.ej.

state => ({ lecture: state.lecture })
2
SamVK 9 sep. 2018 a las 20:05

Tienes dos problemas aquí.

Está definiendo la función mapStateToProps como el primer argumento para connect incorrecto. Como muchas respuestas explican esto ahora, debe usarlo así, esto:

export default connect(
  state => ( { lecture: state.lecture } ),
  dispatch => bindActionCreators(actionCreators, dispatch)
)(LectureTable);

Ahora, tienes un lecture accesorio como tu estado. Puede alcanzarlo con this.props.lecture. Pero en su método componentWillMount, está intentando registrarlo como this.props.test. Debería ser this.props.lecture.test.

Por cierto, intente utilizar componentDidMount en lugar de componentWillMount ya que quedará en desuso en futuras versiones.

0
devserkan 9 sep. 2018 a las 20:30

Rick, tu argumento de conexión debería ser algo como:

export default connect( state => {
    return {
      test: state.lecture // Or any value
    }
})(LectureTable);

Estás tratando de iniciar sesión en la consola con el accesorio test, por lo que debes incluirlo en tu llamada de conexión.

1
Davo 9 sep. 2018 a las 20:20

Creo que en su ejemplo weatherForecasts es un objeto. En su ejemplo, lectures parece ser una matriz, por lo que sugiero reescribir su función mapStateToProps de esta manera si solo necesita obtener el accesorio lectures

state => ({ lectures: state.lectures})

Si necesita el state completo, puede tener state => state para poder acceder a los accesorios this.props.test y this.props.lectures

Tenga en cuenta que mapStateToProps debe devolver un object, no un array. Por cierto, en su reductor el nombre del campo es lectures (plural) no lecture por lo que state => state.lecture será undefined

1
Olivier Boissé 9 sep. 2018 a las 20:10