redux-react在react子组件中操作props的方法是什么?

What's the redux-react way to manipulate props in react children component

本文关键字:props 方法 是什么 操作 react 组件 redux-react      更新时间:2023-09-26

我是Redux和React的新手。我试图实现一个反应组件的排序,但据我所知,你不允许在Redux中操纵props。在redux-react中,正确的方法是什么?

这是我的组件

import React, { Component, PropTypes } from 'react';
import _ from 'lodash';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as ArticlesActions from '../../actions/ArticlesActions';
import { ArticleList } from '../../components';
class ArticleListApp extends Component {
  static propTypes = {
    articles: PropTypes.array.isRequired,
    next: PropTypes.string.isRequired,
    actions: PropTypes.object.isRequired
  };
  componentWillMount() {
    this.props.actions.fetchArticles('57bde6d6e4b0dc55a4f018e0');
  }
  renderLoadMoreButton() {
    if (!_.isEmpty(this.props.next)) {
      return (
        <button type="button" className="btn btn-link center-block" onClick={this.props.actions.fetchMoreArticles.bind(this, this.props.next)}>Load More</button>
      );
    }
    return '';
  }
  render () {
    return (
      <div>
        <ArticleList articles={this.props.articles}/>
        <div className="row">
          <div className="col-md-12 center-block">
            {this.renderLoadMoreButton()}
          </div>
        </div>
      </div>
    );
  }
}
function mapStateToProps(state) {
  return {
    articles: state.articleList.articleList,
    next: state.articleList.next
  };
}
function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators(ArticlesActions, dispatch)
  };
}
export default connect(
  mapStateToProps,
  mapDispatchToProps
)(ArticleListApp);

一旦我得到articles,我将其传递给ArticleList组分我认为它是还原反应中的dump组分

import React, { Component, PropTypes } from 'react';
export default class ArticleList extends Component {
  static propTypes = {
    articles: PropTypes.array.isRequired
  }
  constructor(props, context) {
    super(props, context);
  }
  renderList() {
    return this.props.articles.map((article) =>
       <tr>
        <td>{article.title}</td>
        <td>Author</td>
        <td>{article.words}</td>
        <td>ago</td>
       </tr>
    );
  }
  sortArticles() {
    this.props.articles = this.props.articles.sort(); // I'm not allowed to do this. 
  }
  render() {
    return (
        <table className="table table-hover">
          <thead>
            <tr>
              <th>UNPUBLISHED ARTICLES ({this.props.articles.length})</th>
              <th>AUTHOR</th>
              <th>WORDS</th>
              <th onClick={this.sortArticles.bind(this)}>SUBMITTED</th>
            </tr>
          </thead>
          <tbody>
            {this.renderList()}
          </tbody>
        </table>
    );
  }
}

在这个组件中,我希望有一个排序功能,用户可以单击列并按该列对整个表进行排序。

articles对象的例子是

[{title: 'title', word: 10}, {title: 'title', word: 5}]

如果我理解正确的话,那么有两种方法:

  1. 物品应保持在减速器中,排序或不排序,取决于用户交互。从技术上讲,这是通过有"排序"动作触发(由容器),然后减速器处理该事件通过改变其状态(返回一个新的状态,是以前的数组,但排序)。无论这是如何实现的,这都会引入一个问题:订阅了articles reducer的任何组件将始终获得一个排序列表。这是你想要的吗?也许"排序"显示是ui组件状态的一部分并且是特定于该组件的所以....

  2. 让减速器保持未排序的数组,并有两个不同的组件(或一个组件与一个额外的道具说明,如果它的"排序"或不),并在该组件的渲染功能,要么排序或不排序,根据组件容器给出的道具。从技术上讲,这是通过让容器组件有一个状态(已排序或未排序)来完成的,该状态作为prop传递给视图组件。

如果你是react/redux的新手,我说的对你来说没什么意义,我不介意添加代码-但我认为你的问题是关于原理的,而不是关于实际的代码。

所以Redux流组件将调用一个action, reducer将会监听这个action,从而更新状态。任何容器(封装在连接函数中的组件)都将使用新状态重新呈现自己。

所以你在这里要做的是有一个监听器来监听你的ArticleList组件(哑组件)中列的onClick事件,它向父组件ArticleListApp(容器,或智能组件)触发一个函数。这将导致容器触发一个动作,比如props。例如sortByColumn('AUTHOR', 'asc')。这个动作应该在你的actions文件中定义基本上是这样的

function sortByColumn(columnName, order) {
   return {
      type: 'SORT_BY_COLUMN',
      columnName: columnName,
      order: order
   }
}

Reducer将监听该操作,并使用新订单中列出的商品更新您的商店。

当更新发生时,侦听该状态的容器将使用新状态重新呈现自身。你可以把点击处理程序放在每一列上,你想调用父列和它想排序的列。

你的组件看起来像这样:

import React, { Component, PropTypes } from 'react';
import _ from 'lodash';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import * as ArticlesActions from '../../actions/ArticlesActions';
import { ArticleList } from '../../components';
class ArticleListApp extends Component {
  static propTypes = {
    articles: PropTypes.array.isRequired,
    next: PropTypes.string.isRequired,
    actions: PropTypes.object.isRequired
  };
  componentWillMount() {
    this.props.actions.fetchArticles('57bde6d6e4b0dc55a4f018e0');
  }
  renderLoadMoreButton() {
    if (!_.isEmpty(this.props.next)) {
      return (
        <button type="button" className="btn btn-link center-block" onClick={this.props.actions.fetchMoreArticles.bind(this, this.props.next)}>Load More</button>
      );
    }
    return '';
  }
  render () {
    return (
      <div>
        <ArticleList articles={this.props.articles} 
                     handleSortByCol={this.props.sortByColumn(columnName, sortOrder)} />
        <div className="row">
          <div className="col-md-12 center-block">
            {this.renderLoadMoreButton()}
          </div>
        </div>
      </div>
    );
  }
}
function mapStateToProps(state) {
  return {
    articles: state.articleList.articleList,
    next: state.articleList.next
  };
}
function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators(ArticlesActions, dispatch)
  };
}
export default connect(
  mapStateToProps,
  mapDispatchToProps
)(ArticleListApp);

另一个哑组件是:

import React, { Component, PropTypes } from 'react';
export default class ArticleList extends Component {
  static propTypes = {
    articles: PropTypes.array.isRequired
  }
  constructor(props, context) {
    super(props, context);
  }
  renderList() {
    return this.props.articles.map((article) =>
       <tr>
        <td>{article.title}</td>
        <td>Author</td>
        <td>{article.words}</td>
        <td>ago</td>
       </tr>
    );
  }
  sortArticles() {
    this.props.handleSortByCol('author', 'asc');
  }
  render() {
    return (
        <table className="table table-hover">
          <thead>
            <tr>
              <th>UNPUBLISHED ARTICLES ({this.props.articles.length})</th>
              <th>AUTHOR</th>
              <th>WORDS</th>
              <th onClick={this.sortArticles.bind(this)}>SUBMITTED</th>
            </tr>
          </thead>
          <tbody>
            {this.renderList()}
          </tbody>
        </table>
    );
  }