如何在反应服务和组件之间进行通信?
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;
我创建了一个调用 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;