我是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
组件,我认为它是redux-react中的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}]
答案 0 :(得分:2)
因此Redux流程组件将调用reducer将侦听的操作,从而更新状态。监听该状态的任何容器(包含在connect函数中的组件)将使用新状态重新呈现自身。
所以你想要做的是有一个监听器,它监听你的ArticleList组件(哑组件)中列的onClick事件,它会向父组件,ArticleListApp(容器或智能组件)发出一个函数。 。这将导致容器触发一个动作,例如props.sortByColumn(&#39; AUTHOR&#39;,#39; asc&#39;)。该动作应该在你的动作文件中定义,基本上就是这样的
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>
);
}
答案 1 :(得分:2)
如果我理解正确,那么有两种方法可以解决这个问题:
根据用户的互动,文章应保存在reducer中,排序或不排序。从技术上讲,这是通过(由容器)触发“sort”操作然后通过更改其状态(返回作为前一个数组但已排序的新状态)处理该事件的reducer来完成的。无论如何完成,这都会带来一个问题:订阅文章reducer的任何组件都将获得一个排序列表。这是你想要的吗?也许“排序”显示是ui组件状态的一部分,并且特定于该组件......
让reducer保留未排序的数组,并且有两个不同的组件(或者一个组件带有额外的支柱,说明它是否“已排序”)以及在此组件的渲染功能期间,是排序还是不排序根据组件容器给出的prop,排序。从技术上讲,这是通过让容器组件具有作为prop传递给视图组件的状态(已排序或未排序)来完成的。
如果你是刚接触/ redux的新手,我说的话对你来说没什么意义,我不介意添加代码 - 但我认为你的问题是关于原则而不是实际的代码。