Javascript Redux:私人/公共选择器的更好方式

Javascript Redux:私人/公共选择器的更好方式,javascript,redux,react-redux,Javascript,Redux,React Redux,正如所建议的,私有选择器作为公共选择器重复使用,以在完整状态下使用 切片上使用的专用选择器 在完全状态下使用的公共选择器 但这将导致: 重复代码 在公共选择器的命名空间中溢出 有没有更好的方法来组织选择器? 原始示例: 根还原器和公共选择器: // reducers/index.js import todos, * as fromTodos from './todos'; // Reducer export default combineReducers({ todos });

正如所建议的,私有选择器作为公共选择器重复使用,以在完整状态下使用

  • 切片上使用的专用选择器
  • 在完全状态下使用的公共选择器
但这将导致:

  • 重复代码
  • 在公共选择器的命名空间中溢出
有没有更好的方法来组织选择器?

原始示例: 根还原器和公共选择器:

// reducers/index.js
import todos, * as fromTodos from './todos';

// Reducer
export default combineReducers({
    todos
});

// Private selector
getVisibleTodos(state, filter) {
    return fromTodos.getVisibleTodos(state.todos, filter);
}
// reducers/todos.js

// Reducer
export default (state, action) => {
    switch(action.type){
    case 'ADD_TODO':
        // ...
        break;
    // Handle other actions ...
    }
}

// Private selector
getVisibleTodos(state, filter) {
    switch(filter) {
    case 'all':
        return todos;
    case 'completed':
        return state.filter(t => t.completed);
    // Other cases ...
    }
}
const mapStateToProps = (state, {params}) => ({
    todos: getVisibleTodos(state, params.filter || 'all')
});
切片缩减器和专用选择器:

// reducers/index.js
import todos, * as fromTodos from './todos';

// Reducer
export default combineReducers({
    todos
});

// Private selector
getVisibleTodos(state, filter) {
    return fromTodos.getVisibleTodos(state.todos, filter);
}
// reducers/todos.js

// Reducer
export default (state, action) => {
    switch(action.type){
    case 'ADD_TODO':
        // ...
        break;
    // Handle other actions ...
    }
}

// Private selector
getVisibleTodos(state, filter) {
    switch(filter) {
    case 'all':
        return todos;
    case 'completed':
        return state.filter(t => t.completed);
    // Other cases ...
    }
}
const mapStateToProps = (state, {params}) => ({
    todos: getVisibleTodos(state, params.filter || 'all')
});
使用选择器:

// reducers/index.js
import todos, * as fromTodos from './todos';

// Reducer
export default combineReducers({
    todos
});

// Private selector
getVisibleTodos(state, filter) {
    return fromTodos.getVisibleTodos(state.todos, filter);
}
// reducers/todos.js

// Reducer
export default (state, action) => {
    switch(action.type){
    case 'ADD_TODO':
        // ...
        break;
    // Handle other actions ...
    }
}

// Private selector
getVisibleTodos(state, filter) {
    switch(filter) {
    case 'all':
        return todos;
    case 'completed':
        return state.filter(t => t.completed);
    // Other cases ...
    }
}
const mapStateToProps = (state, {params}) => ({
    todos: getVisibleTodos(state, params.filter || 'all')
});

将私有选择器复制为公共选择器有一些优点和缺点

我相信复制在分离关注点和封装逻辑方面对您有好处,也就是说,无论何时您必须更改从redux状态获取某些数据的逻辑,您都不必修改您的组件。 此外,您的组件不应该拥有对与其相关的状态部分进行切片的逻辑

然而,它确实会导致一些不必要的重复。 我可以想出一个带有库的解决方案,但它可能需要您在单独的文件中列出所有选择器。 使用glob,您可以遍历选择器文件夹中的所有js文件(您可以增加复杂性,忽略某些文件查看其实例原型,或者其他文件),并将它们合并到根reducer文件中。 我在express应用程序中见过这种技术,通过为每条路线创建一个js文件,将所有路线组装在一个地方

希望它的清晰和帮助你


编辑-->我强烈建议您仔细查看一下,以全面了解为什么在root reducer中将私有选择器复制为公共选择器是有益的(尽管我知道您开始认为您也可以将公共选择器放置在单独的文件中…)

你能提供一个有效的例子吗?我已经增强了这个例子。请注意,将选择器重新定义一次为私有选择器,另一次为公共选择器。问题在于避免这种重复。选择器通常是纯函数,因此可以毫无问题地移动到它们自己的模块中。我想从中获得灵感