如何在反应服务和组件之间进行通信?

How to communicate between react service and a component?

我创建了一个调用 rest api 的 util.js 文件,我需要在这个 util(不是组件)和其他组件之间进行通信。

例如,在登录时,如果未能引发事件,登录组件将捕获并采取相应行动。

不确定这是否是正确的方法(我是新手),该怎么做?

我实施了一个 flux 解决方案(尽管 redux appraoch 可能就足够了,一个商店——这是其余服务——可以完成这项工作)

调度员:

 import { Dispatcher } from 'flux';

export default new Dispatcher();

RestService(商店):

import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import App from '../App';

import {EventEmitter} from 'events';
import dispatcher from '../Dispatcher';
import * as Actions from "../actions/Actions";

const baseUrl = 'http:/.../WebServices/api';

class ApiService extends EventEmitter {

    constructor() {
        super();

        this.updateStatus = this.updateStatus.bind(this);

        this.state = {
            loginFailed: false
        }
    }

    getLoginStatus() {
        return this.state.loginFailed;
    }

    updateStatus(status) {
        //this.setState({loginFailed: true});
        this.state.loginFailed = status;
    }

    // module.exports = {

        /*export function*/ login(userName, password) {
            fetch(baseUrl + '/SessionManager/login?userName='
                + userName + '&password=' + password,
                {
                    //method: 'GET',
                    //credentials: "same-origin",
                    //mode: "no-cors",
                    //headers: headers
                    //'Content-Type': 'application/json'
                }
            ).then(
                (response) => {
                    localStorage.setItem('Response', JSON.stringify(response))
                    //console.log("Headers ======>", JSON.stringify(response.headers));

                    // Inspect the headers in the response
                    response.headers.forEach(console.log);
                    // OR you can do this
                    for (let entry of response.headers.entries()) {
                        console.log(entry);
                    }

                    // let sid = getSessionCookie(); //document.cookie.match('sid=([^;]*)');
                    // console.log("Session Id: ", sid);
                    // localStorage.setItem('session', sid)

                    // let headers = response.headers.get('Set-Cookie')
                    // console.log("Headers: ", headers);
                    // localStorage.setItem('headers', headers)

                    if (response.status < 200 || response.status > 300) {
                        // console.log('Looks like there was a problem. Status Code: ' + response.status);
                        // this.state.showError = true;
                        // this.state.errorMessage = 'Please enter a valid credentials.';

                        //this.setState({loginFailed: true});
                        this.updateStatus(true);
                        this.emit("statusChanged", response);

                        return;
                    } else {
                        //window.location.href = '/main';
                        ReactDOM.render(<App user={userName}/>,
                            document.getElementById('root'));
                    }

                    // Examine the text in the response
                    // response.json().then(function(data) {
                    //     console.log(data);
                    // });
                }
            ).catch((error) => {
                console.error(error);
            });
        }

        /*export function*/ getProjectDetails() {
            //let params = this.getSession();
            //console.log('Params....', params);


            fetch(baseUrl + '/ProjectManager/getProjectDetails',
                {
                    //   //credentials: "include",
                    //   //credentials: "same-origin",
                    //   //crossdomain: true,
                    //   //mode: 'no-cors',
                    //headers: headers
                }
            )
                .then(res => res.json())
                .then((data) => {
                    this.setState({projectsDetails: data})
                    console.log(data);
                })
                .catch(console.log);
        }
    // }

    handleActions(action) {
        switch(action.type) {
            case "LOGIN": {
                this.login(action.user, action.password);
                //this.emit("change");
            }
            // case "LOGIN_FAILURE": {
            //     this.setState({loginFailed: true});
            //     this.emit("change");
            // }
        }
    }
}

// const service = new ApiService();
// // Register dispatcher
// dispatcher.register(service.handleActions.bind(service));
// // Expose dispatcher globally
// window.dispatcher = dispatcher;

export default ApiService;

操作:

import dispatcher from '../Dispatcher';

export function login(user, password) {

    dispatcher.dispatch({
        type: "LOGIN",
        user: user,
        password: password
    })

}

登录组件:

import React, { Component } from 'react';
import {Button, Form, TextInput} from 'carbon-components-react';
import './Login.css';
//import * as service from  '../services/RestService.js';
import ApiService from '../stores/RestService.js';
import ReactDOM from "react-dom";
import App from "../App";
import * as Actions from "../actions/Actions";
import dispatcher from "../Dispatcher";


const apiService = new ApiService();

// Register dispatcher
dispatcher.register(apiService.handleActions.bind(apiService));
// Expose dispatcher globally
window.dispatcher = dispatcher;


class Login extends Component {

    //errorMessage;
    service;
    getLoginStatus;

    constructor(props) {
        super(props);
        this.getLoginStatus = this.getLoginStatus.bind(this);

        //this.service = new ApiService();
        this.state = {
            userName: '',
            password: '',
            // errorMessage: '',
            //showError: false,
            loginFailed: false
        }

        apiService.on('statusChanged', this.getLoginStatus);
    }

    componentWillMount() {
        apiService.on('change', this.getLoginStatus);
    }

    componentWillUnmount() {
        apiService.removeListener("change", this.getLoginStatus);
    }

    getLoginStatus() {
        this.setState({
            loginFailed: apiService.getLoginStatus()
        });
    }

    handleUserChange(e) {
        this.setState({ userName: e.target.value });
    }

    handlePasswordChange(e) {
        this.setState({ password: e.target.value });
    }

    handleSubmit = (event) => {
        event.preventDefault();

        //this.service.login(this.state.userName, this.state.password);
        Actions.login(this.state.userName, this.state.password);
    }


    render() {
        const {loginFailed} = this.state;
        return (
            <div className="App">
                <header className="App-header">

                    <table width="100%" className="Toolbar1">
                        <tbody>
                        <tr>
                            <td width="90%">
                                <h2>My App</h2>
                            </td>
                            <td>
                                <Button className="button">
                                    Help
                                </Button>
                            </td>
                        </tr>
                        </tbody>
                    </table>

                </header>

                <body classname="App-body">
                    <table width="25%" align="center" className="bordered spaced centered">
                        <tbody>
                        <tr>
                            <td width="75%">Welcome to ...</td>
                            <td>Ver: 1.0.0</td>
                        </tr>
                        <tr>
                            <td colSpan="2">
                                <Form onSubmit={this.handleSubmit}>
                                        <TextInput
                                            className="wide"
                                            id="txtUser"
                                            labelText=""
                                            placeholder="User Name"
                                            required
                                            onChange={ this.handleUserChange.bind(this) }
                                        />
                                        <br/>
                                        <TextInput
                                            className="wide"
                                            id="txtPassword"
                                            type="password"
                                            required
                                            labelText=""
                                            placeholder="Password"
                                            // pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,}"
                                            // {...InvalidPasswordProps}
                                            required
                                            onChange={ this.handlePasswordChange.bind(this)}
                                        />
                                        <br/>
                                        <Button type="submit" className="button wide"
                                                //onSubmit={this.handleSubmit}
                                                //onClick={this.handleClick}
                                        >
                                            Login
                                        </Button>
                                    <br/><br/>
                                </Form>
                            </td>
                        </tr>
                        </tbody>
                    </table>

                    {/*<spane style={{color: 'red'}}><b>Please enter valid credentials.</b></spane>*/}
                    <div style={{color: 'red'}} className="alert alert-danger centered2">
                        { loginFailed ? <span color="Red"><strong>Error!</strong> Please enter valid credentials.</span> : null }
                    </div>
                </body>

                <footer>

                </footer>

            </div>
        );
    }
}

export default Login;