反应可重用状态修改方法或组件

时间:2018-08-13 11:51:45

标签: javascript reactjs react-component

我的应用程序中有2个仪表板,一个用于设备,另一个用于桌面。他们两个都需要一种可以修改状态的方法。并且此方法包含条件语句,该条件语句确定状态下要更新的值。对于我的情况,桌面和设备仪表板都可以绝对使用此方法来更改所需的状态。现在,要实现这一点,我所了解的是,我必须将此方法放在有状态的组件DesktopDashboard和DeviceDashboard中,从而使我的代码变得多余。我无法确定可以从这两个组件中拉出这种特定状态修改方法并将其从一个地方用作通用方法的方式。下面是我的代码:

webDashboard组件

import React, { Fragment, Component } from 'react';
import JourneyList from './JourneyList';
import CONSTANTS from './Constants';
class webDashboard extends Component {
    constructor(props) {
        super(props);

        this.state = {
            journeyMessageList: [{ messageId: XYPZ, type: CONSTANTS.TEXT, author: CONSTANTS.SYSTEM, data: { text: MESSAGE_CONSTANTS.HOW_MAY_I_HELP_YOU }, time: new Date()},
            { messageId: XYPZ, type: CONSTANTS.ENQUIRY_OPTIONS, author: CONSTANTS.SYSTEM, data: MESSAGE_CONSTANTS.ENQUIRY_OPTIONS, time: new Date()} ]
        };

    }

    updateMyState = (source, typedText) => {
     this.setState({
            journeyMessageList: [...this.state.journeyMessageList, 
                    { messageId: XXXX, type: CONSTANTS.TEXT, author: CONSTANTS.ME, data: { text: typedText }, time: new Date()},
                ]
        });
        if(CONSTANTS.SOURCE_USER_INPUT.MDN === source) {

            this.setState({
                journeyMessageList: [...this.state.journeyMessageList.filter((ele) => ele.type !== CONSTANTS.MDN_USER_INPUT),
                    { messageId: 'dfsdf', type: CONSTANTS.TEXT, author: CONSTANTS.ME, data: { text: typedText }, time: new Date()},
                    { messageId: 'dfsdf', type: CONSTANTS.TEXT, author: CONSTANTS.SYSTEM, data: { text: MESSAGE_CONSTANTS.ASK_SSS }, time: new Date()},
                    { messageId: 'dfsdf', type: CONSTANTS.SSS_USER_INPUT, data: { text: "INPUTBOX" }, author: CONSTANTS.SYSTEM, time: new Date()}
                ]  
            });
        } else if(CONSTANTS.SOURCE_USER_INPUT.NRIC === source) {
            this.setState({
                journeyMessageList: [...this.state.journeyMessageList.filter((ele) => ele.type !== CONSTANTS.NRIC_USER_INPUT),
                    { messageId: 'ghfgh', type: CONSTANTS.TEXT, author: CONSTANTS.ME, data: { text: typedText }, time: new Date()},
                    { messageId: 'ghfgh', type: CONSTANTS.TEXT, author: CONSTANTS.SYSTEM, data: { text: MESSAGE_CONSTANTS.ELIGIBLE_FOR_SERVICE }, time: new Date()},
                    { messageId: 'ghfgh', type: CONSTANTS.CONFIRM_CURRENT_DEVICE, author: CONSTANTS.SYSTEM, data: MESSAGE_CONSTANTS.CONFIRM_CURRENT_DEVICE, time: new Date()}
                ]
            });
        }elsee if(Many Such Conditions){
            .....
        }elsee if(Many Such Conditions){
            .....
        }elsee if(Many Such Conditions){
            .....
        }else{
            .....
        }
    }

    render() {
        return (
            <Fragment> <JourneyList messages={this.state.journeyMessageList} 
                    updateJourneyList={this.updateMyState} />
            </Fragment>
        );
    }

};

export default webDashboard;

deviceDashboard组件

import React, { Fragment, Component } from 'react';
import DeviceChatWindow from './DeviceChatWindow';
import CONSTANTS from './Constants';
class deviceDashboard extends Component {
    constructor(props) {
        super(props);

        this.state = {
            journeyMessageList: [{ messageId: XYPZ, type: CONSTANTS.TEXT, author: CONSTANTS.SYSTEM, data: { text: MESSAGE_CONSTANTS.HOW_MAY_I_HELP_YOU }, time: new Date()},
            { messageId: XYPZ, type: CONSTANTS.ENQUIRY_OPTIONS, author: CONSTANTS.SYSTEM, data: MESSAGE_CONSTANTS.ENQUIRY_OPTIONS, time: new Date()} ]
        };

    }

    updateMyState = (source, typedText) => {
     this.setState({
            journeyMessageList: [...this.state.journeyMessageList, 
                    { messageId: XXXX, type: CONSTANTS.TEXT, author: CONSTANTS.ME, data: { text: typedText }, time: new Date()},
                ]
        });
        if(CONSTANTS.SOURCE_USER_INPUT.MDN === source) {

            this.setState({
                journeyMessageList: [...this.state.journeyMessageList.filter((ele) => ele.type !== CONSTANTS.MDN_USER_INPUT),
                    { messageId: 'dfsdf', type: CONSTANTS.TEXT, author: CONSTANTS.ME, data: { text: typedText }, time: new Date()},
                    { messageId: 'dfsdf', type: CONSTANTS.TEXT, author: CONSTANTS.SYSTEM, data: { text: MESSAGE_CONSTANTS.ASK_SSS }, time: new Date()},
                    { messageId: 'dfsdf', type: CONSTANTS.SSS_USER_INPUT, data: { text: "INPUTBOX" }, author: CONSTANTS.SYSTEM, time: new Date()}
                ]  
            });
        } else if(CONSTANTS.SOURCE_USER_INPUT.NRIC === source) {
            this.setState({
                journeyMessageList: [...this.state.journeyMessageList.filter((ele) => ele.type !== CONSTANTS.NRIC_USER_INPUT),
                    { messageId: 'ghfgh', type: CONSTANTS.TEXT, author: CONSTANTS.ME, data: { text: typedText }, time: new Date()},
                    { messageId: 'ghfgh', type: CONSTANTS.TEXT, author: CONSTANTS.SYSTEM, data: { text: MESSAGE_CONSTANTS.ELIGIBLE_FOR_SERVICE }, time: new Date()},
                    { messageId: 'ghfgh', type: CONSTANTS.CONFIRM_CURRENT_DEVICE, author: CONSTANTS.SYSTEM, data: MESSAGE_CONSTANTS.CONFIRM_CURRENT_DEVICE, time: new Date()}
                ]
            });
        }elsee if(Many Such Conditions){
            .....
        }elsee if(Many Such Conditions){
            .....
        }elsee if(Many Such Conditions){
            .....
        }else{
            .....
        }
    }

    render() {
        return (
            <Fragment>  <div id="appBody" className="row app-body">
                    <div id="chatWindow" className="col-md-9 app-message-window">
                        <DeviceChatWindow
                            journeyMessageList={this.state.journeyMessageList}
                            updateJourneyList={this.updateMyState}
                        />
                    </div>

                </div>
            </Fragment>
        );
    }

};

export default deviceDashboard;

在这里,我想将方法​​ updateMyState 用作可重用的方法,以避免重复,但是我无法弄清楚如何在一个普通的地方使用它每当调用/重发组件调用状态时,都可以更改状态。

注意:constants.jsx包含简单的键/值对常量,例如:

const CONSTANTS = {
  TEXT:"Hi There",
ME:"me",
...
...
}

1 个答案:

答案 0 :(得分:2)

setState() also accepts a function作为参数传递了stateprops并应返回新状态。您可以将更新逻辑提取到静态函数中,例如:

// in myModule.js

const updateState = (state, props) => {
    // calculate new state
    // const newState = ...

    return newState;
}

然后像这样使用它:

import updateState from 'myModule';

class MyComponent extends Component {

    updateMyState = () => this.setState(updateState);

    render() {
        return (
            <JourneyList messages={this.state.journeyMessageList} 
                updateJourneyList={this.updateMyState} />
        );
    }
}

当然,您也可以向该函数添加任意参数:

const updateState = (state, props, source, typedText) => {/* calculate new state */}

用法:

import updateState from 'myModule';

class MyComponent extends Component {

    updateMyState = (source, typedText) => this.setState(
        (state, props) => updateState(state, props, source, typedText)
    );

    render() {
        return (
            <JourneyList messages={this.state.journeyMessageList} 
                updateJourneyList={this.updateMyState} />
        );
    }
}