首页 > 解决方案 > MapDispatchToProps 返回一个函数

问题描述

我尝试从我的 firebase 数据库中阅读我的文章,但我无法让它工作。

这是我的数据库:

myDB-myid
  articles
    1
     body: "Lorem Ipsum Dolor si damet blablabla"
     createdAt: 12345
     subtitle: "ça promet beaucoup d'autres supers articles"
     title: "Mon premier article"
    2
     body: "Encore du Lorem Ipsum et bla et bla et bla..."
     createdAt: 34567
    subtitle: "Vous avez aimé le premier ? Le deuxième va vous..."
     title: "Et voici le deuxième article"

我的组件应该呈现所有文章的列表,ArticlePage

import React from 'react';
import { connect } from 'react-redux';
import Article from './Article';
import { startSetArticles } from '../../actions/articles';

const ArticlesPage = props => (
      <div className="articles-wrapper">
        <div className="container">
        {console.log(props.articles)}
        {
          props.articles.length === 0 ? (
            <p>No article</p>
            ) : (
            props.articles.map(a => {
              return <Article key={a.id} {...a}/>
            })
            )
          }
        </div>
      </div>
      );

const mapDispatchToProps = dispatch => ({
  articles: () => dispatch(startSetArticles())
});

export default connect(undefined, mapDispatchToProps)(ArticlesPage);

我的商店:

import { createStore, combineReducers, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import authReducer from '../reducers/auth';
import articlesReducer from '../reducers/articles';

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

export default () => {
  const store = createStore(
    combineReducers({
      auth: authReducer,
      articles: articlesReducer
    }),
    composeEnhancers(applyMiddleware(thunk))
  );

  return store;
};

我的行动action/articles.js

import database from '../firebase/firebase';

// SET_ARTICLES
export const setArticles = articles => ({
  type: 'SET_ARTICLES',
  articles
});

export const startSetArticles = () => {
  return dispatch => {
    return database.ref('articles').once('value').then(snapshot => {
      const articles = [];

      snapshot.forEach(a => {
        articles.push({
          id: a.key,
          ...a.val()
        });
      });
      dispatch(setArticles(articles));
    });
  };
};

我的减速机reducers/articles.js

const articlesReducerDefaultState = [];

export default (state = articlesReducerDefaultState, action) => {
  switch (action.type) {
      case 'SET_ARTICLES':
        return action.articles;
    default:
      return state;
  }
};

但我不能让它工作。这是console.log(props.articles)组件的控制台输出:

ƒ articles() {
      return dispatch((0, _articles.startSetArticles)());
    }

任何想法 ?它应该呈现两个帖子,但它只返回函数本身。(我从三元运算符那里得到“无文章”)

标签: reactjsreduxreact-redux

解决方案


articles是一个函数,因为这正是你所做的:

const mapDispatchToProps = dispatch => ({
  articles: () => dispatch(startSetArticles())
});

将 dispatch映射到 props 并将它映射到一个调用的 prop articles,它是一个调度动作的函数。这里没有惊喜。但我想您还想要将状态映射到道具,您可以使用 connect 的第一个参数来执行此操作:

const mapStateToProps = state => ({ articlesList: state.articles });
export default connect(mapStateToProps, mapDispatchToProps)(ArticlesPage);

现在,如果你这样做console.log(props),你应该得到具有两个属性的 Object:

{
  articles, // a function from mapDispatchToProps
  articlesList // a function from mapStateToProps 
}

编辑:

但是,您仍然需要调用您的文章函数来使用 firebase 获取数据并填充 redux 存储。启动异步数据的最佳方法是使用 componentDidMount() 钩子:

class ArticlesPage extends React.Component {
  componentDidMount() {
    this.props.articles();  // use mapped function to dispatch redux action
  }

  render() {
    // render data with array from the store
    return (
      <div className="articles-wrapper">
        <div className="container">
          {this.props.articlesList.length === 0 ? (
            <p>No article</p>
          ) : (
            this.props.articlesList.map(a => {
              return <Article key={a.id} {...a} />;
            })
          )}
        </div>
      </div>
    );
  }
}

推荐阅读