├── .babelrc ├── .gitignore ├── LICENSE ├── README.md ├── package-lock.json ├── package.json ├── src ├── App │ ├── App.jsx │ └── index.js ├── HomePage │ ├── HomePage.jsx │ └── index.js ├── _services │ ├── index.js │ └── message.service.js ├── index.html └── index.jsx └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "react", 4 | "env", 5 | "stage-0" 6 | ] 7 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | 6 | # Runtime data 7 | pids 8 | *.pid 9 | *.seed 10 | 11 | # Directory for instrumented libs generated by jscoverage/JSCover 12 | lib-cov 13 | 14 | # Coverage directory used by tools like istanbul 15 | coverage 16 | 17 | # nyc test coverage 18 | .nyc_output 19 | 20 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 21 | .grunt 22 | 23 | # node-waf configuration 24 | .lock-wscript 25 | 26 | # Compiled binary addons (http://nodejs.org/api/addons.html) 27 | build/Release 28 | 29 | # Dependency directories 30 | node_modules 31 | jspm_packages 32 | typings 33 | 34 | # Optional npm cache directory 35 | .npm 36 | 37 | # Optional REPL history 38 | .node_repl_history -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Jason Watmore 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # react-rxjs-communicating-between-components 2 | 3 | React + RxJS - Communicating Between Components with Observable & Subject 4 | 5 | To see a demo and further details go to http://jasonwatmore.com/post/2019/02/13/react-rxjs-communicating-between-components-with-observable-subject -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-rxjs-communicating-between-components", 3 | "version": "1.0.0", 4 | "repository": { 5 | "type": "git", 6 | "url": "https://github.com/cornflourblue/react-rxjs-communicating-between-components.git" 7 | }, 8 | "license": "MIT", 9 | "scripts": { 10 | "start": "webpack-dev-server --open" 11 | }, 12 | "dependencies": { 13 | "react": "^16.0.0", 14 | "react-dom": "^16.0.0", 15 | "react-router-dom": "^4.1.2", 16 | "rxjs": "^6.3.3" 17 | }, 18 | "devDependencies": { 19 | "babel-core": "^6.26.0", 20 | "babel-loader": "^7.1.5", 21 | "babel-preset-env": "^1.6.1", 22 | "babel-preset-react": "^6.16.0", 23 | "babel-preset-stage-0": "^6.24.1", 24 | "html-webpack-plugin": "^3.2.0", 25 | "path": "^0.12.7", 26 | "webpack": "^4.15.0", 27 | "webpack-cli": "^3.0.8", 28 | "webpack-dev-server": "^3.1.3" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/App/App.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { BrowserRouter as Router, Route } from 'react-router-dom'; 3 | 4 | import { messageService } from '@/_services'; 5 | import { HomePage } from '@/HomePage'; 6 | 7 | class App extends React.Component { 8 | constructor(props) { 9 | super(props); 10 | 11 | this.state = { 12 | messages: [] 13 | }; 14 | } 15 | 16 | componentDidMount() { 17 | // subscribe to home component messages 18 | this.subscription = messageService.getMessage().subscribe(message => { 19 | if (message) { 20 | // add message to local state if not empty 21 | this.setState({ messages: [...this.state.messages, message] }); 22 | } else { 23 | // clear messages when empty message received 24 | this.setState({ messages: [] }); 25 | } 26 | }); 27 | } 28 | 29 | componentWillUnmount() { 30 | // unsubscribe to ensure no memory leaks 31 | this.subscription.unsubscribe(); 32 | } 33 | 34 | render() { 35 | const { messages } = this.state; 36 | return ( 37 | 38 |
39 |
40 |
41 |
42 |
43 | {messages.map((message, index) => 44 |
{message.text}
45 | )} 46 | 47 |
48 |
49 |
50 |
51 |
52 |
53 | ); 54 | } 55 | } 56 | 57 | export { App }; -------------------------------------------------------------------------------- /src/App/index.js: -------------------------------------------------------------------------------- 1 | export * from './App'; -------------------------------------------------------------------------------- /src/HomePage/HomePage.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { messageService } from '@/_services'; 4 | 5 | class HomePage extends React.Component { 6 | sendMessage() { 7 | // send message to subscribers via observable subject 8 | messageService.sendMessage('Message from Home Page Component to App Component!'); 9 | } 10 | 11 | clearMessages() { 12 | // clear messages 13 | messageService.clearMessages(); 14 | } 15 | 16 | render() { 17 | return ( 18 |
19 |

React + RxJS Component Communication

20 | 21 | 22 |
23 | ); 24 | } 25 | } 26 | 27 | export { HomePage }; -------------------------------------------------------------------------------- /src/HomePage/index.js: -------------------------------------------------------------------------------- 1 | export * from './HomePage'; -------------------------------------------------------------------------------- /src/_services/index.js: -------------------------------------------------------------------------------- 1 | export * from './message.service'; 2 | -------------------------------------------------------------------------------- /src/_services/message.service.js: -------------------------------------------------------------------------------- 1 | import { Subject } from 'rxjs'; 2 | 3 | const subject = new Subject(); 4 | 5 | export const messageService = { 6 | sendMessage: message => subject.next({ text: message }), 7 | clearMessages: () => subject.next(), 8 | getMessage: () => subject.asObservable() 9 | }; 10 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | React + RxJS - Communicating Between Components with Observable & Subject 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 |
16 | 17 | 18 |
19 |

20 | React + RxJS - Communicating Between Components with Observable & Subject 21 |

22 |

23 | JasonWatmore.com 24 |

25 |
26 | 27 | -------------------------------------------------------------------------------- /src/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from 'react-dom'; 3 | 4 | import { App } from './App'; 5 | 6 | render( 7 | , 8 | document.getElementById('app') 9 | ); -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | var HtmlWebpackPlugin = require('html-webpack-plugin'); 2 | const path = require('path'); 3 | 4 | module.exports = { 5 | mode: 'development', 6 | resolve: { 7 | extensions: ['.js', '.jsx'] 8 | }, 9 | module: { 10 | rules: [ 11 | { 12 | test: /\.jsx?$/, 13 | loader: 'babel-loader' 14 | } 15 | ] 16 | }, 17 | resolve: { 18 | extensions: ['.js', '.jsx'], 19 | alias: { 20 | '@': path.resolve(__dirname, 'src/'), 21 | } 22 | }, 23 | plugins: [new HtmlWebpackPlugin({ 24 | template: './src/index.html' 25 | })], 26 | devServer: { 27 | historyApiFallback: true 28 | } 29 | } --------------------------------------------------------------------------------