@ackmann-dickenson/redux-search 中文文档教程
redux-search
一个 redux 实现,可以轻松地为任何结果添加搜索、排序和分页放。
Installation
npm i @ackmann-dickenson/redux-search
Usage
一般来说,您需要在三个位置包含 ReduxSearch
。
1. Connect to your app's reducers
该包依赖于 reducer 来管理其状态,SearchTable
组件期望该状态在给定变量中可用。 因为这, 当您的主要应用程序 reducer 正在连接其所有特定的 reducer 时,您还需要包括该包的 reducer,如下所示:
import {combineReducers} from 'redux'
import {routerStateReducer} from 'redux-router'
import ReduxSearch from '@ackmann-dickenson/redux-search'
const rootReducer = combineReducers({
router: routerStateReducer,
reduxSearches: ReduxSearch.reduxSearches
})
export default rootReducer
2. Render the ReduxSearch.SearchTable component
该包的核心是一个组件,它显示一个具有搜索、排序和分页功能的数据表。 它需要一个函数,您将使用该函数将数据提取到 填充表。 实际的表格行也必须作为应用程序状态的函数提供,每次提供时都会更新 fetch 函数被调用。 这是一个示例组件。
import React, {PropTypes} from 'react'
import ReduxSearch from '@ackmann-dickenson/redux-search'
import {searchProducts} from './actions'
const headers = [{
field: 'name',
label: 'Name',
isSortable: true,
query: { type: 'like' }
}, {
field: 'price',
label: 'Price',
isSortable: true,
query: { type: 'range' }
}]
export default class ProductsDataTable extends React.Component {
static propTypes = {
rows: PropTypes.object.isRequired
}
render() {
return (
<ReduxSearch.SearchTable
{...this.props}
fetch={searchProducts}
searchId={'products-index'}
field={'name'}
headers={headers}
rows={this.props.rows} />
)
}
}
3. Access your search state from your action creator
当组件被渲染时,它会分派一个动作,使状态用新的搜索更新。 为了从您的动作创建者访问该状态, 您的函数将需要接受 searchId
参数并使用包提供的一些实用程序检索状态。 例如
import api from "root/api"
import ReduxSearch from '@ackmann-dickenson/redux-search'
export const PRODUCTS_REQUESTED = "PRODUCTS_REQUESTED"
export const PRODUCTS_RECEIVED = "PRODUCTS_RECEIVED"
export const PRODUCTS_RECEIVED_ERROR = "PRODUCTS_RECEIVED_ERROR"
export function searchProducts(searchId) {
return function(dispatch, getState) {
dispatch({type: PRODUCTS_REQUESTED})
const search = ReduxSearch.querify(getState(), searchId, 'name')
return api.getProducts(search)
.then(resp => {
dispatch({
type: PRODUCTS_RECEIVED,
results: resp.data.results
});
return resp;
})
.catch(resp => {
dispatch({
type: PRODUCTS_RECEIVED_ERROR,
errors: resp.data.errors
})
})
}
}
Providing table rows
,如何提供表格行完全取决于您。 只要行是你的 reducer 由于你的 action creator 而更新的状态的函数,SearchTable
就会显示它们。 下面是一个容器组件示例,它将包装上面显示的 ProductsDataTable
。
import React, {PropTypes} from 'react'
import {connect} from 'react-redux'
import {fetchProducts} from './actions'
import {ProductsDataTable} from './ProductsDataTable'
export class Products extends React.Component {
static propTypes = {
products: PropTypes.object.isRequired
}
rows() {
return this.props.products.map(p => {
return (
<tr key={p.product_id}>
<td>{p.name}</td>
<td>{p.price}</td>
</tr>
)
})
}
render() {
return (
<div>
<div className="wrapper wrapper-content animated fadeInRight">
<div className="row">
<ProductsDataTable
rows={this.rows()} />
</div>
</div>
</div>
)
}
}
function mapStateToProps(state) {
return {
products: state.products.get("products")
}
}
export const ProductsContainer = connect(mapStateToProps)(Products)
Server side expectations
还预计从服务器返回的 JSON 数据将包含一个 total_count
属性,这是必需的 使分页正常工作。
Contributing
要做出贡献,请创建一个分支并提交拉取请求。 未经测试,将不会接受来自组织外部的拉取请求。
Testing
可以使用 npm test
运行测试套件。 可以使用npm test debug
实现命令行调试。 测试套件目前是最小的,需要扩展。 请不要提交未经测试的新作品。
redux-search
A redux implementation to easily add search, sort, and pagination to any result set.
Installation
npm i @ackmann-dickenson/redux-search
Usage
Generally speaking, there are three locations where you'll want to include ReduxSearch
.
1. Connect to your app's reducers
This package relies on a reducer to manage its state, and the SearchTable
component expects that state to be available in a given variable. Because of this, when your main application reducer is connecting all of its specific reducers, you'll need to include this package's reducer as well, like so:
import {combineReducers} from 'redux'
import {routerStateReducer} from 'redux-router'
import ReduxSearch from '@ackmann-dickenson/redux-search'
const rootReducer = combineReducers({
router: routerStateReducer,
reduxSearches: ReduxSearch.reduxSearches
})
export default rootReducer
2. Render the ReduxSearch.SearchTable component
The heart of this package is a component that displays a datatable with searching, sorting, and pagination. It requires a function that you'll use to fetch the data to populate the table. The actual table rows must also be provided as a prop that is a function of your application state, which would be updated every time the supplied fetch function is called. Here's an example component.
import React, {PropTypes} from 'react'
import ReduxSearch from '@ackmann-dickenson/redux-search'
import {searchProducts} from './actions'
const headers = [{
field: 'name',
label: 'Name',
isSortable: true,
query: { type: 'like' }
}, {
field: 'price',
label: 'Price',
isSortable: true,
query: { type: 'range' }
}]
export default class ProductsDataTable extends React.Component {
static propTypes = {
rows: PropTypes.object.isRequired
}
render() {
return (
<ReduxSearch.SearchTable
{...this.props}
fetch={searchProducts}
searchId={'products-index'}
field={'name'}
headers={headers}
rows={this.props.rows} />
)
}
}
3. Access your search state from your action creator
When the component is rendered, it will dispatch an action that causes the state to be updated with a new search. In order to access that state from your action creator, your function will need to accept a searchId
parameter and retrieve the state using some utilities provided by the package. E.g.
import api from "root/api"
import ReduxSearch from '@ackmann-dickenson/redux-search'
export const PRODUCTS_REQUESTED = "PRODUCTS_REQUESTED"
export const PRODUCTS_RECEIVED = "PRODUCTS_RECEIVED"
export const PRODUCTS_RECEIVED_ERROR = "PRODUCTS_RECEIVED_ERROR"
export function searchProducts(searchId) {
return function(dispatch, getState) {
dispatch({type: PRODUCTS_REQUESTED})
const search = ReduxSearch.querify(getState(), searchId, 'name')
return api.getProducts(search)
.then(resp => {
dispatch({
type: PRODUCTS_RECEIVED,
results: resp.data.results
});
return resp;
})
.catch(resp => {
dispatch({
type: PRODUCTS_RECEIVED_ERROR,
errors: resp.data.errors
})
})
}
}
Providing table rows
It's really up to you how you provide the table rows. As long as the rows are a function of the state that your reducer is updating as a result of your action creator, the SearchTable
will display them. Here's an example of a container component that would wrap the ProductsDataTable
shown above.
import React, {PropTypes} from 'react'
import {connect} from 'react-redux'
import {fetchProducts} from './actions'
import {ProductsDataTable} from './ProductsDataTable'
export class Products extends React.Component {
static propTypes = {
products: PropTypes.object.isRequired
}
rows() {
return this.props.products.map(p => {
return (
<tr key={p.product_id}>
<td>{p.name}</td>
<td>{p.price}</td>
</tr>
)
})
}
render() {
return (
<div>
<div className="wrapper wrapper-content animated fadeInRight">
<div className="row">
<ProductsDataTable
rows={this.rows()} />
</div>
</div>
</div>
)
}
}
function mapStateToProps(state) {
return {
products: state.products.get("products")
}
}
export const ProductsContainer = connect(mapStateToProps)(Products)
Server side expectations
It's also expected that the JSON data coming back from the server will include a total_count
property which is required for the pagination to work correctly.
Contributing
To contribute, please create a fork and submit pull requests. Pull requests from outside of the organization will not be accepted without tests.
Testing
The test suite can be run with npm test
. Command line debugging can be achieved with npm test debug
. The test suite is currently minimal and needs to be expanded. Please do not submit new work without tests.