React Redux this.props是否为空?

时间:2018-11-09 12:17:14

标签: reactjs redux react-redux

我在项目中使用 react-boilerplate 结构。 我有一个容器LoginForm,该容器对用户进行身份验证并以状态存储来自API的响应。 我想从另一个容器NavHeader访问此响应,该容器是标题,它应该呈现这些信息。

NavHeader中的this.props未定义。有人可以指出我在哪里出问题了。

  

更新:我试图将化极器和动作移至App(根)容器,仍然没有运气。显然,我没有做正确的事,也无法弄清楚。任何帮助将不胜感激!

UserLoginForm容器

index.js

export class UserLoginForm extends Component {
  constructor(props) {
    super(props);
  }

onLoginSubmit(e) {
    e.preventDefault();
    const { email, password } = this.state;
    this.props.dispatch(authorize(email, password));
  }
  render() {
    return (
      <HeroBannerStyle>
          <form>
                <InputField name="email" />
                <InputField type="password" />
                <Button onClick={this.onLoginSubmit}/>
          </form>
      </HeroBannerStyle>
    );}}

const mapStateToProps = createStructuredSelector({
  userLoginForm: makeSelectUserLoginForm(),
}); 
==> This essentially does this: state.get('userLoginForm', initialState);

const withConnect = connect(mapStateToProps);
const withReducer = injectReducer({ key: 'userLoginForm', reducer });
const withSaga = injectSaga({ key: 'userLoginForm', saga });

export default compose(withReducer,withSaga,withConnect(UserLoginForm);

actions.js

export function authSuccess(payload) {
  return {
    type: AUTH_SUCCESS, payload: {user: payload},
  };
}

reducer.js

export const authorize = (email, password) => ({
  type: AUTH_REQUEST,
  payload: {email, password},
});
export const initialState = fromJS({
  user: null
});

const userLoginFormReducer = (state = initialState, { type, payload }) => {
  switch (type) {
    case AUTH_SUCCESS: {
      return {
        ...state,
        user: payload.data,
      };
    }
    default:
      return state;
  }
};

export default userLoginFormReducer;

saga.js

function* fetchUserReqSaga({ payload: { email, password } }) {
  try {
    const response = yield call(fetchUser, { email, password });
    yield put({ type: AUTH_SUCCESS, payload: response });
} catch (error) {}
}

function fetchUser({ email, password }) {
  return usersAPI.post('/login', {email, password,});
}

容器NavHeader

index.js

class NavHeader extends Component {
  constructor(props) {
    super(props);
    }       
      componentDidMount() {
        console.log('this.props..', this.props);//THIS IS UNDEFINED
      }

      render() {
        return (
              <div>{this.props.user}</div> // THIS IS EMPTY
        );      
}}
    const mapStateToProps = state => {
      console.log(state); //THIS DOES NOT HAVE 'userLoginForm'
      return {
        user: state.get('userLoginForm')
      }
    };

    const withConnect = connect(mapStateToProps);
    const withReducer = injectReducer({ key: 'navHeader', reducer });
    const withSaga = injectSaga({ key: 'navHeader', saga });
    export default compose(withReducer,withSaga,withConnect)(NavHeader);

1 个答案:

答案 0 :(得分:0)

组件和(rootReducer,rootSaga)连接到商店,所有动作和道具都通过商店来进行。您可以在浏览器中进行调试,以查看数据的运行情况。

这是官方文档。这很容易而且很短,但是了解所有这些reduce,action,props东西至关重要。还有一个小的codepen片段,以了解其工作原理。

Redux docs

Short redux example

这也是类似项目的摘录。从断点处添加了更多行。

UPD:

它从连接到存储的rootReducer中获取数据。初始化存储并连接所有减速器时,将调用CombineReducers:

export interface RootState {
    books: BooksState;
    authors: AuthorsState;
}

const rootReducer: Reducer<RootState> = combineReducers<RootState>({  
    authors: authorReducer,
    books: booksReducer

})
export default rootReducer;

减速器返回有效载荷(数据)后,由选择器获取:

export const getData = (state: RootState) => state.books.data

它用于mapStateToProps中,我使用 connect 调用高阶函数,并从存储中收集数据并创建容器。 Compose不是Redux,如果使用它,则必须检查中间件的顺序(compose(m1,m2,m3 ...)从右到左):

const mapStateToProps = (state: RootState) => ({
  books: getData(state), 
  pagination: getPagination(state),
  loading: getLoadingStatus(state),
  error: getError(state),

})

    export default connect(mapStateToProps, { loadBooks, searchBook, removeBook, addBook,  editBook, sortBook, 
    })(FilterableBooksTable);

然后涉及“聪明”组件:

export interface BooksTableProps {
    readonly books: Array<Book>;
    loadBooks: (pagination: Pagination) => object; 
}

export interface BookFormProps {
    addBook: (name: string, author: string, cost: number, genre: string) => object;
}

type FilterableBooksTableProps = BooksTableProps & BookFormProps;

export default class FilterableBooksTable extends React.Component<FilterableBooksTableProps> {

render() {
  const {
    books,
    loadBooks,
    addBook,                   
  } = this.props

  return (        
      <div>
          <Row>
            <Col span={4}>
              <BookForm
                addBook={addBook}                    
                >
            </Col>
            <Col span={16}>
              <BookTable        
                books={books}
                loadBooks={loadBooks}            
              />
            </Col>                
          </Row>
      </div>        
  )
  }

最后数据到达“愚蠢”组件:

render() {
   const {
       books                
   } = this.props;

  return (
    <div>           
      <Table          
        dataSource={books}          
        ...
      />
    </div>                
  )
}

我不知道您的商店配置是什么,所以我将添加与所有sagas,reducer相连的我的矿井:

import { Store, createStore, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga';
import { composeWithDevTools } from 'redux-devtools-extension';
import rootReducer, { RootState } from '@redux/rootReducer';
import rootSaga from '@redux/sagas';

export default function configureStore(initialState?: RootState): Store<RootState> {
  const sagaMiddleware = createSagaMiddleware();
  const middlewares = [sagaMiddleware];

  const composeEnhancers = composeWithDevTools({});

  const enhancer = composeEnhancers(
    applyMiddleware(...middlewares)
  );

  const store = createStore(
    rootReducer,
    initialState!,
    enhancer,
  );

  if (module.hot) {
    module.hot.accept('@redux/rootReducer', () => {
      const nextRootReducer = require('@redux/rootReducer').default;
      store.replaceReducer(nextRootReducer);
    });
  }

  sagaMiddleware.run(rootSaga);

  return store;
}