2017-01-19 1 views
0

Я участвую в процессе обучения React Native с Redux и не могу обернуть голову тем, как получить доступ к хранилищу/actionCreators из моих компонентов. Я чувствую, что я пробовал десять или около того вариантов кода, наблюдал за большинством видеороликов Дэна Абрамова Egghead (несколько раз) и до сих пор не понимаю, что я делаю неправильно. Я думаю, что лучшее объяснение, которое я видел до сих пор, является принятым ответом здесь: Redux, Do I have to import store in all my containers if I want to have access to the data?Проблема с доступом к хранилищу и вызовом actionCreators

Ошибка, которую я получаю: undefined не является объектом (оценка «state.clinic.drName»). Вот соответствующие биты кода:

Я проходящее в магазин через провайдера (так я думаю):

index.ios.js 
import clinicReducer from './reducers/clinic'; 

import { createStore, combineReducers } from 'redux'; 
import { Provider } from 'react-redux'; 

const rootReducer = combineReducers({ 
    clinic : clinicReducer 
}); 

let store = createStore(combineReducers({clinicReducer})); 

//testing - log every action out 
let unsubscribe = store.subscribe(() => 
    console.log(store.getState()) 
); 

class ReactShoeApp extends React.Component { 
render() { 
    return (
     <Provider store={store}> 
      <ReactNative.NavigatorIOS 
       style={styles.container} 
       initialRoute={{ 
        title: 'React Shoe App', 
        component: Index 
      }}/> 
     </Provider> 
    ); 
} 
} 

Вот мой actionCreator:

export const CLINIC_DR_NAME_UPDATE = 'CLINIC_DR_NAME_UPDATE_UPDATE'; 

export function updateClinicDrName(newValue) { 
    return {type: CLINIC_DR_NAME_UPDATE, value: newValue}; 
} 

Вот мой редуктор :

import { 
    CLINIC_DR_NAME_UPDATE 
} from '../actions/'; 

let cloneObject = function(obj) { 
    return JSON.parse(JSON.stringify(obj)); 
}; 

const initialState = { 
    drName : null 
}; 

export default function clinicReducer(state = initialState, action) { 
    switch (action.type) { 
     case CLINIC_DR_NAME_UPDATE: 
      return { 
       ...state, 
       drName: action.value 
      }; 
      default: 
       return state || newState; 
     } 
    } 

и вот мой компонент:

import { bindActionCreators } from 'redux'; 
import { connect } from 'react-redux'; 
import * as Actions from '../actions'; 

const mapStateToProps = function(state){ 
    return { 
     drName: state.clinic.drName, 
    } 
}; 

const mapDispatchToProps = function (dispatch) { 
    return bindActionCreators({ 
     updateClinicDrName: Actions.updateClinicDrName, 
    }, dispatch) 
}; 


//class definition 
class Clinic extends React.Component { 
    constructor(props) { 
     super(props); 
} 

render() { 

    return (
     <View style={styles.rowContainer}> 
      <View style={styles.row}> 
       <TextGroup label={'Dr. Name'} placeholder={'placeholder'} value={this.props.drName} onChangeText={(text) => this.handlers.onNameChange({text})}></TextGroup> 
       <TextGroup label={'City'} placeholder={'placeholder'}></TextGroup> 
      </View> 
     </View> 
    ); 
} 

} 

export default connect(mapStateToProps, mapDispatchToProps)(Clinic); 

Все, что я пытаюсь сделать, это обновить магазин (clinic.drName), когда пользователь вводит имя в текстовой группе Dr Name. Любая помощь приветствуется.

ответ

0

Проблема заключается в том, что вы несовместимы с тем, как вы вызываете combineReducers() с именем ожидаемого фрагмента. Это распространенная ошибка. Вы определяете объект с ключом clinicReducer, но ожидаете, что данные будут иметь ключ с именем .

Для получения подробной информации см. http://redux.js.org/docs/recipes/reducers/UsingCombineReducers.html#defining-state-shape.

Кроме того, ваша clinicReducer() функция выглядит странно, и имеет несколько вопросов:

  • Не доступ к переменным вне функции, как вы с newState.
  • Не делайте такого глубокого клонирования (за http://redux.js.org/docs/faq/Performance.html#performance-clone-state). Вместо этого используйте «мелкое клонирование», чтобы обновить состояние, если это необходимо (см. Примеры на http://redux.js.org/docs/recipes/reducers/ImmutableUpdatePatterns.html).
  • Похоже, что редуктор выполняет двойное вложение данных, к которым он пытается получить доступ.

Я думаю вы хотите что-то более, как:

// clinicReducer.js 

const initialState = { 
    drName : null 
}; 

export default function clinicReducer(state = initialState, action) { 
    switch(action.type) { 
     case CLINIC_DR_NAME_UPDATE: { 
      return { 
       ...state, 
       drName : actino.value 
      }; 
     } 
     default: return state   
    } 
} 


// index.js 

import clinicReducer from "./reducers/clinic"; 

const rootReducer = combineReducers({ 
    clinic : clinicReducer 
}); 
+1

Спасибо! Я изменил свой вопрос, чтобы он содержал правильный код, и он работает сейчас. – miarde

0

Какие ошибки вы получаете? Я вижу две проблемы с тем, что у вас есть.

  1. newState.clinic.drName = action.value; должно быть выбрано типаError. Поэтому для этой работы вам необходимо изменить NewState к:

    const newState = { clinic: {} }

  2. Что такое this.handlers.onNameChange({text})? Я думаю, вам нужно изменить это на this.props.updateClinicDrName(text).

Смежные вопросы