MapDispatchToProps返回一个函数

时间:2018-05-23 15:41:40

标签: reactjs redux react-redux

我尝试从我的firebase数据库中读取我的文章,但我无法使其工作。

这是我的DB:

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

任何想法?它应该呈现两个帖子,但它只返回函数本身。 (我从三元运营商那里得到了一篇文章&#39;

3 个答案:

答案 0 :(得分:1)

myarray = [np.array([ 4.12101269], dtype=float), np.array([ 4.44119978], dtype=float), np.array([ 4.30688763], dtype=float), np.array([ 4.80304432], dtype=float), np.array([ 4.47734165], dtype=float), np.array([ 4.88290167])] np.array(myarray).flatten() # array([ 4.12101269, 4.44119978, 4.30688763, 4.80304432, 4.47734165, 4.88290167]) 是一个函数,因为这正是你所做的:

articles

将调度映射到道具,并将其映射到名为const mapDispatchToProps = dispatch => ({ articles: () => dispatch(startSetArticles()) }); 的道具,这是一个调度动作的函数。这里不足为奇。但我想你还想要的是将状态映射到道具,你可以用连接的第一个参数来做:

articles

现在,如果你做const mapStateToProps = state => ({ articlesList: state.articles }); export default connect(mapStateToProps, mapDispatchToProps)(ArticlesPage); ,你应该得到两个属性的对象:

console.log(props)

修改

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

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

答案 1 :(得分:1)

我认为你只连接到商店,但从未调用函数startSetArticles()。尝试添加(这将适用于您当前的mapDispatchToProps)

  componentDidMount() {
    this.props.articles()
  }

这应该调用该函数,该函数应该更新您的商店。

我会建议而不是:

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

你应该这样做:

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

然后你必须这样做,这更有意义。

  componentDidMount() {
    this.props.startSetArticles()
  }

我认为您的混淆是关于如何使用mapDispatchToProps。当您mapDispatchToProps时,DOES NOT会立即调用该函数。您仍然需要在组件中的某个位置调用该函数。在你的情况下,componenetDidMount是有道理的。

然后你需要添加mapStateToProps,它将连接到商店并实际获取数据。

这是一个有效的例子:

export class Morphology extends React.Component {
  componentDidMount() {
    document.title = 'Eflows | Morphology';
    this.props.fetchGeoSites();
  }

  render() {
    return (
      <div>
        <div style={styles.banner} />
        <Layout geoSites={this.props.geoSites} />
      </div>
    );
  }
}

Morphology.propTypes = {
  fetchGeoSites: PropTypes.func,
  geoSites: PropTypes.array,
};

const mapStateToProps = state => {
  return {
    geoSites: state.geoSite.geoSites,
  };
};

const mapDispatchToProps = dispatch => {
  return {
    fetchGeoSites: () => dispatch(fetchGeoSites()),
  };
};

我使用相同的方法,您可以使用此repo更多地查看它: https://github.com/leogoesger/eflow-client

答案 2 :(得分:0)

您应该使用connect的第一个参数来获取articles状态。

connect(state => ({ articles: state.articles }), ...)

要设置articles州,您需要在startSetArticles或您声明componentDidMount的文件中调用store(如果您希望调用它)当应用加载时store.dispatch(startSetArticles())