如何使用 redux-subspace 以相同的操作重用 reducer

How to reuse reducer with same action using redux-subspace

我正在使用 React、semantic-ui-react、redux-subspace 开发一个小型应用程序。 我有许多不同的表,当用户单击其中一个单元格时,该值应该出现在控制台上,但单击时结果未定义。我正在尝试重用减速器。不同实例的相同操作。 我感谢任何让我走向正确方向的评论。

PartA.js

此组件呈现 Table 并用 <SubspaceProvider> 包装。

<Segment inverted color='black'>
<h1>Age </h1>
{ this.state.toggle ?
<SubspaceProvider mapState={state => state.withSpouseAge} namespace="withSpouseAge">
    <TableForm 
        headers={spouse_ageHeaders} 
        rows={spouse_ageData}  
        namespace={'withSpouseAge'}
    />
</SubspaceProvider> :
<SubspaceProvider mapState={state => state.withoutSpouseAge} namespace="withoutSpouseAge">
    <TableForm 
        headers={withoutSpouse_ageHeader} 
        rows={withoutSpouse_ageData}
        namespace={'withoutSpouseAge'}
    />
</SubspaceProvider> }

TableForm.js

此组件 return Table 带有数据,这是我要实现 onClick 方法的地方。

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Table } from 'semantic-ui-react';
import { select } from '../actions';

const shortid = require('shortid');

class TableForm extends Component {
    constructor(props){
        super(props);
        this.state = {
            activeIndex: 0,
        }
        this.handleOnClick = this.handleOnClick.bind(this);
        this.isCellActive = this.isCellActive.bind(this);
    };

    isCellActive(index) {
        this.setState({ activeIndex: index });
    }

    handleOnClick(index, point) {
        this.isCellActive(index);
        this.props.onSelect(point);
    };

    tableForm = ({ headers, rows }) => {
        const customRenderRow = ({ factor, point, point2 }, index ) => ({
            key: shortid.generate(),
            cells: [
                <Table.Cell content={factor || 'N/A'} />,
                <Table.Cell 
                    content={point}
                    active={index === this.state.activeIndex}
                    textAlign={'center'} 
                    selectable 
                    onClick={() => this.handleOnClick(index, point)}
                />,
                <Table.Cell 
                    content={point2}
                    textAlign={'center'} 
                    selectable
                />
            ],
        });
        return (
            <Table
                size='large'
                padded
                striped
                celled
                verticalAlign={'middle'} 
                headerRow={this.props.headers} 
                renderBodyRow={customRenderRow} 
                tableData={this.props.rows}
            />
        )
    };

    render() {
        console.log(this.props.withSpouseAgePoint);
        const { headers, rows } = this.props;
        return (
            <div>
                {this.tableForm(headers, rows)}
            </div>
        );  
    }
};

const mapDispatchToProps = (dispatch) => {
    return {
        onSelect: (point) => {dispatch(select(point))},
    }
}

const mapStateToProps = state => {
    return {
        withSpouseAgePoint: state.withSpouseAge,
        withSpouseLoePoint: state.withSpouseLoe,
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(TableForm);

行动

import {
    SELECT,
} from './types';

export const select = (points) => ({
    type: 'SELECT',
    points,
});

Reducer.js

import { SELECT } from '../actions/types';

const INITIAL_STATE = {
    point: 0,
};

const selectionReducer = (state = INITIAL_STATE, action) => {
    switch (action.type) {
        case 'SELECT':
            return { ...state, point: state.point + action.points };
        default:
            return state;
    }
};

export default selectionReducer;

减速机index.js

import { createStore, combineReducers } from 'redux';
import { subspace, namespaced } from 'redux-subspace';
import selectionReducer from './selectionReducer';
import toggleReducer from './toggleReducer';

const reducers = combineReducers({
    withSpouseAge: namespaced('withSpouseAge')(selectionReducer),
    withSpouseLoe: namespaced('withSpouseLoe')(selectionReducer),
    withSpouseOlp: namespaced('withSpouseOlp')(selectionReducer),
    withSpouseOlp2: namespaced('withSpouseOlp2')(selectionReducer),
    withSpouseExp: namespaced('withSpouseExp')(selectionReducer),    
    withoutSpouseAge: namespaced('withoutSpouseAge')(selectionReducer),
    withoutSpouseLoe: namespaced('withoutSpouseLoe')(selectionReducer),
    withoutSpouseOlp: namespaced('withoutSpouseOlp')(selectionReducer),
    withoutSpouseOlp2: namespaced('withoutSpouseOlp2')(selectionReducer),
    withoutSpouseExp: namespaced('withoutSpouseExp')(selectionReducer),
    toggle: toggleReducer,
});

更新

我在下面添加了Table表单组件

const mapDispatchToProps = (dispatch) => {
    return {
        onSelect: (point) => {dispatch(select(point))},
    }
}

const mapStateToProps = state => {
    return {
        withSpouseAgePoint: state.withSpouseAge,
        withSpouseLoePoint: state.withSpouseLoe,
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(TableForm);

在 handleOnClick 上实施 this.props.onSelect(point)。它仍然显示相同的结果 undefined。我通过 getState() 检查了商店状态。 consloe.log。我认为我对 redux-subspace 的实现是错误的。我上传了整个 TableForm 组件并更新了 reducer。请帮帮我!

更新 2

我替换了 mapStateToProps,它就像变魔术一样奏效。再次感谢@JustinTRoss。 但还有另一个问题,当我单击单元格时,所有状态都以相同的值出现。 。我的计划是每个州都有自己的价值存储。

const mapStateToProps = state => {
    return {
        withSpouseAgePoint: state,
        withoutSpouseAge: state,
    }
}

您已经将组件命名空间命名为 withSpouseAge,并将状态映射到 SubspaceProvider 中的 state.withSpouseAge。因此,您正在调用 state.withSpouseAge.withSpouseAge (undefined).

的等价物

另一个潜在的问题是您调用 connect 时使用的签名。从您提供的片段中,无法确定 'select' 的值。通常,使用 2 个函数调用 connect,通常名为 mapStateToProps 和 mapDispatchToProps。您正在使用函数和 object 调用 connect。这是来自 http://www.sohamkamani.com/blog/2017/03/31/react-redux-connect-explained/#connect 的示例:

import {connect} from 'react-redux'

const TodoItem = ({todo, destroyTodo}) => {
  return (
    <div>
      {todo.text}
      <span onClick={destroyTodo}> x </span>
    </div>
  )
}

const mapStateToProps = state => {
  return {
    todo : state.todos[0]
  }
}

const mapDispatchToProps = dispatch => {
  return {
    destroyTodo : () => dispatch({
      type : 'DESTROY_TODO'
    })
  }
}

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoItem)

此外,还有一个问题,尽管它还没有影响到您:您使用 2 个参数(headers 和行)调用 this.tableForm,而您定义了 this.tableForm 函数获取单个参数并解构 'headers' 和 'rows' 属性。