From a312b51b9cef27cd5c5a16ebb1f9a1679edefc85 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 2 Oct 2025 17:32:24 +0000 Subject: [PATCH] Migrate service layer from AngularJS to React - Create React CommentService using fetch API - Create React AuthorService using fetch API - Implement ServiceProvider with legacy Context API (React 15) - Update CommentList to use React services via context - Remove unused render helper function - Maintain backward compatibility for Angular components Co-Authored-By: Ben Carpenter-Nwanyanwu --- src/components/CommentList/presenter.js | 30 +++++++++------- src/services/AngularReactHelper/index.js | 17 ++++----- src/services/AuthorService/reactService.js | 25 +++++++++++++ src/services/CommentService/reactService.js | 22 ++++++++++++ src/services/ServiceProvider.js | 39 +++++++++++++++++++++ 5 files changed, 112 insertions(+), 21 deletions(-) create mode 100644 src/services/AuthorService/reactService.js create mode 100644 src/services/CommentService/reactService.js create mode 100644 src/services/ServiceProvider.js diff --git a/src/components/CommentList/presenter.js b/src/components/CommentList/presenter.js index 9a84931..616be36 100644 --- a/src/components/CommentList/presenter.js +++ b/src/components/CommentList/presenter.js @@ -1,20 +1,24 @@ -import React, { PropTypes } from 'react'; +import React, { Component, PropTypes } from 'react'; import Comment from '../Comment'; -import { getAngularService } from '../../services/AngularReactHelper'; -const CommentList = (props) => { - const AuthorService = getAngularService(document, 'AuthorService'); - const toComment = (c, i) => - ; - return ( -
- { props.comments.map(toComment) } -
- ); -}; +export default class CommentList extends Component { + render() { + const { authorService } = this.context; + const toComment = (c, i) => + ; + + return ( +
+ { this.props.comments.map(toComment) } +
+ ); + } +} CommentList.propTypes = { comments: PropTypes.array.isRequired, }; -export default CommentList; +CommentList.contextTypes = { + authorService: PropTypes.object, +}; diff --git a/src/services/AngularReactHelper/index.js b/src/services/AngularReactHelper/index.js index 8fae697..d30ef69 100644 --- a/src/services/AngularReactHelper/index.js +++ b/src/services/AngularReactHelper/index.js @@ -2,13 +2,7 @@ import angular from 'angular'; import ReactDOM from 'react-dom'; import React from 'react'; import { mapValues } from 'lodash'; - -function render(element, Component, props) { - ReactDOM.render( - , - element, - ); -} +import ServiceProvider from '../ServiceProvider'; function toBindings(propTypes) { return mapValues(propTypes, () => '<'); @@ -30,7 +24,14 @@ export function reactToAngularComponent(Component) { return { bindings: toBindings(propTypes), controller: /*@ngInject*/ function controller($scope, $element) { - this.$onChanges = () => render($element[0], Component, toProps(propTypes, this)); + this.$onChanges = () => { + const WrappedComponent = ( + + + + ); + ReactDOM.render(WrappedComponent, $element[0]); + }; this.$onDestroy = () => ReactDOM.unmountComponentAtNode($element[0]); }, }; diff --git a/src/services/AuthorService/reactService.js b/src/services/AuthorService/reactService.js new file mode 100644 index 0000000..06a7e56 --- /dev/null +++ b/src/services/AuthorService/reactService.js @@ -0,0 +1,25 @@ +const AUTHOR_URI = 'http://localhost:3004/authors'; + +export default class AuthorService { + constructor() { + this.authors = {}; + } + + queryAuthors() { + return fetch(AUTHOR_URI) + .then(resp => resp.json()) + .then(data => this.setAuthors(data)); + } + + setAuthors(authors) { + this.authors = authors.reduce((authorMap, author) => { + authorMap[author.id] = author; + return authorMap; + }, this.authors); + return authors; + } + + getAuthor(id) { + return this.authors[id]; + } +} diff --git a/src/services/CommentService/reactService.js b/src/services/CommentService/reactService.js new file mode 100644 index 0000000..74809fc --- /dev/null +++ b/src/services/CommentService/reactService.js @@ -0,0 +1,22 @@ +const COMMENTS_URI = 'http://localhost:3004/comments'; + +export default class CommentService { + constructor() { + this.comments = []; + } + + queryComments() { + return fetch(COMMENTS_URI) + .then(resp => resp.json()) + .then(data => this.setComments(data)); + } + + getComments() { + return this.comments; + } + + setComments(comments) { + this.comments = comments; + return comments; + } +} diff --git a/src/services/ServiceProvider.js b/src/services/ServiceProvider.js new file mode 100644 index 0000000..da2f34e --- /dev/null +++ b/src/services/ServiceProvider.js @@ -0,0 +1,39 @@ +import { Component, PropTypes } from 'react'; +import CommentService from './CommentService/reactService'; +import AuthorService from './AuthorService/reactService'; + +export default class ServiceProvider extends Component { + constructor(props) { + super(props); + this.commentService = new CommentService(); + this.authorService = new AuthorService(); + this.state = { + authorsLoaded: false, + }; + } + + getChildContext() { + return { + commentService: this.commentService, + authorService: this.authorService, + }; + } + + componentDidMount() { + this.authorService.queryAuthors().then(() => { + this.setState({ authorsLoaded: true }); + }); + } + + render() { + if (!this.state.authorsLoaded) { + return null; + } + return this.props.children; + } +} + +ServiceProvider.childContextTypes = { + commentService: PropTypes.object, + authorService: PropTypes.object, +};