Repository: aneagoie/robofriends-redux Branch: master Commit: e8e0e3db25e9 Files: 19 Total size: 13.6 KB Directory structure: gitextract_kxxhc1gn/ ├── .gitignore ├── README.md ├── package.json ├── public/ │ ├── index.html │ └── manifest.json └── src/ ├── actions.js ├── api/ │ └── api.js ├── components/ │ ├── Card.js │ ├── CardList.js │ ├── ErrorBoundry.js │ ├── Scroll.js │ └── SearchBox.js ├── constants.js ├── containers/ │ ├── App.css │ └── App.js ├── index.css ├── index.js ├── reducers.js └── registerServiceWorker.js ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # See https://help.github.com/ignore-files/ for more about ignoring files. # dependencies /node_modules # testing /coverage # production /build # misc .DS_Store .env.local .env.development.local .env.test.local .env.production.local npm-debug.log* yarn-debug.log* yarn-error.log* ================================================ FILE: README.md ================================================ # robofriends React + Redux To run the project: 1. Clone this repo 2. Run `npm install` 3. Run `npm start` *visit https://zerotomastery.io/ for more* ================================================ FILE: package.json ================================================ { "name": "robofriends", "version": "0.1.0", "private": true, "dependencies": { "react": "^19.1.1", "react-dom": "^19.1.1", "react-redux": "^9.2.0", "react-scripts": "^5.0.1", "redux": "^5.0.1", "redux-logger": "^3.0.6", "redux-thunk": "^3.1.0", "tachyons": "^4.12.0" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test --env=jsdom", "eject": "react-scripts eject" }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] } } ================================================ FILE: public/index.html ================================================ React App
================================================ FILE: public/manifest.json ================================================ { "short_name": "React App", "name": "Create React App Sample", "icons": [ { "src": "favicon.ico", "sizes": "64x64 32x32 24x24 16x16", "type": "image/x-icon" } ], "start_url": "./index.html", "display": "standalone", "theme_color": "#000000", "background_color": "#ffffff" } ================================================ FILE: src/actions.js ================================================ import { apiCall } from './api/api' import { CHANGE_SEARCHFIELD, REQUEST_ROBOTS_PENDING, REQUEST_ROBOTS_SUCCESS, REQUEST_ROBOTS_FAILED } from './constants' export const setSearchField = (text) => ({ type: CHANGE_SEARCHFIELD, payload: text }) export const requestRobots = () => (dispatch) => { dispatch({ type: REQUEST_ROBOTS_PENDING }) apiCall('https://jsonplaceholder.typicode.com/users') .then(data => dispatch({ type: REQUEST_ROBOTS_SUCCESS, payload: data })) .catch(error => dispatch({ type: REQUEST_ROBOTS_FAILED, payload: error })) } ================================================ FILE: src/api/api.js ================================================ export const apiCall = (link) => fetch(link).then(response => response.json()) ================================================ FILE: src/components/Card.js ================================================ import React from 'react'; const Card = ({ name, email, id }) => { return (
robots

{name}

{email}

); } export default Card; ================================================ FILE: src/components/CardList.js ================================================ import React from 'react'; import Card from './Card'; const CardList = ({ robots }) => { return (
{ robots.map((user, i) => { return ( ); }) }
); } export default CardList; ================================================ FILE: src/components/ErrorBoundry.js ================================================ import React, { Component } from 'react' class ErrorBoundary extends Component { constructor (props) { super(props) this.state = { hasError: false } } componentDidCatch (error, info) { this.setState({ hasError: true }) } render () { if (this.state.hasError) { return

Something went wrong.

} return this.props.children } } export default ErrorBoundary ================================================ FILE: src/components/Scroll.js ================================================ import React from 'react'; const Scroll = (props) => { return (
{props.children}
); }; export default Scroll; ================================================ FILE: src/components/SearchBox.js ================================================ import React from 'react'; const SearchBox = ({ searchfield, searchChange }) => { return (
); } export default SearchBox; ================================================ FILE: src/constants.js ================================================ export const CHANGE_SEARCHFIELD = 'CHANGE_SEARCHFIELD'; export const REQUEST_ROBOTS_PENDING = 'REQUEST_ROBOTS_PENDING'; export const REQUEST_ROBOTS_SUCCESS = 'REQUEST_ROBOTS_SUCCESS'; export const REQUEST_ROBOTS_FAILED = 'REQUEST_ROBOTS_FAILED'; ================================================ FILE: src/containers/App.css ================================================ /* #### Generated By: http://www.cufonfonts.com #### */ @font-face { font-family: 'SEGA LOGO FONT'; font-style: normal; font-weight: normal; src: local('SEGA LOGO FONT'), url('SEGA.woff') format('woff'); } h1 { font-family: 'SEGA LOGO FONT'; font-weight: 200; color: #0ccac4; } ================================================ FILE: src/containers/App.js ================================================ import React, { Component } from 'react'; import { connect } from 'react-redux'; import { setSearchField, requestRobots } from '../actions'; import CardList from '../components/CardList'; import SearchBox from '../components/SearchBox'; import Scroll from '../components/Scroll'; import ErrorBoundry from '../components/ErrorBoundry'; import './App.css'; // parameter state comes from index.js provider store state(rootReducers) const mapStateToProps = (state) => { return { searchField: state.searchRobots.searchField, robots: state.requestRobots.robots, isPending: state.requestRobots.isPending } } // dispatch the DOM changes to call an action. note mapStateToProps returns object, mapDispatchToProps returns function // the function returns an object then uses connect to change the data from redecers. const mapDispatchToProps = (dispatch) => { return { onSearchChange: (event) => dispatch(setSearchField(event.target.value)), onRequestRobots: () => dispatch(requestRobots()) } } class App extends Component { componentDidMount() { this.props.onRequestRobots(); } render() { const { robots, searchField, onSearchChange, isPending } = this.props; const filteredRobots = robots.filter(robot => { return robot.name.toLowerCase().includes(searchField.toLowerCase()); }) return (

RoboFriends

{ isPending ?

Loading

: }
); } } // action done from mapDispatchToProps will channge state from mapStateToProps export default connect(mapStateToProps, mapDispatchToProps)(App) ================================================ FILE: src/index.css ================================================ body { margin: 0; padding: 0; font-family: sans-serif; background: linear-gradient(to left, rgba(7,27,82,1) 0%, rgba(0,128,128,1) 100%); /* w3c */ } ================================================ FILE: src/index.js ================================================ import React from 'react'; // import ReactDOM from 'react-dom'; The new way to import createRoot: import { createRoot } from "react-dom/client"; import { createStore, combineReducers, applyMiddleware } from 'redux'; import { Provider } from 'react-redux'; //import thunkMiddleware from 'redux-thunk'; //NEW way of importing redux-thunk: import { thunk } from 'redux-thunk'; import { createLogger } from 'redux-logger'; import 'tachyons'; import App from './containers/App'; import registerServiceWorker from './registerServiceWorker'; import { requestRobots, searchRobots } from './reducers' import './index.css'; const logger = createLogger() const rootReducers = combineReducers({requestRobots, searchRobots}) const store = createStore(rootReducers, applyMiddleware(thunk, logger)) const root = createRoot(document.getElementById('root')); root.render( ); // ReactDOM.render( // // // , // document.getElementById('root') // ); registerServiceWorker(); ================================================ FILE: src/reducers.js ================================================ import { CHANGE_SEARCHFIELD, REQUEST_ROBOTS_PENDING, REQUEST_ROBOTS_SUCCESS, REQUEST_ROBOTS_FAILED } from './constants'; const initialStateSearch = { searchField: '' } export const searchRobots = (state=initialStateSearch, action={}) => { switch (action.type) { case CHANGE_SEARCHFIELD: return Object.assign({}, state, {searchField: action.payload}) default: return state } } const initialStateRobots = { robots: [], isPending: true } export const requestRobots = (state=initialStateRobots, action={}) => { switch (action.type) { case REQUEST_ROBOTS_PENDING: return Object.assign({}, state, {isPending: true}) case REQUEST_ROBOTS_SUCCESS: return Object.assign({}, state, {robots: action.payload, isPending: false}) case REQUEST_ROBOTS_FAILED: return Object.assign({}, state, {error: action.payload}) default: return state } } ================================================ FILE: src/registerServiceWorker.js ================================================ // In production, we register a service worker to serve assets from local cache. // This lets the app load faster on subsequent visits in production, and gives // it offline capabilities. However, it also means that developers (and users) // will only see deployed updates on the "N+1" visit to a page, since previously // cached resources are updated in the background. // To learn more about the benefits of this model, read https://goo.gl/KwvDNy. // This link also includes instructions on opting out of this behavior. const isLocalhost = Boolean( window.location.hostname === 'localhost' || // [::1] is the IPv6 localhost address. window.location.hostname === '[::1]' || // 127.0.0.1/8 is considered localhost for IPv4. window.location.hostname.match( /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ ) ); export default function register() { if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { // The URL constructor is available in all browsers that support SW. const publicUrl = new URL(process.env.PUBLIC_URL, window.location); if (publicUrl.origin !== window.location.origin) { // Our service worker won't work if PUBLIC_URL is on a different origin // from what our page is served on. This might happen if a CDN is used to // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374 return; } window.addEventListener('load', () => { const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; if (isLocalhost) { // This is running on localhost. Lets check if a service worker still exists or not. checkValidServiceWorker(swUrl); } else { // Is not local host. Just register service worker registerValidSW(swUrl); } }); } } function registerValidSW(swUrl) { navigator.serviceWorker .register(swUrl) .then(registration => { registration.onupdatefound = () => { const installingWorker = registration.installing; installingWorker.onstatechange = () => { if (installingWorker.state === 'installed') { if (navigator.serviceWorker.controller) { // At this point, the old content will have been purged and // the fresh content will have been added to the cache. // It's the perfect time to display a "New content is // available; please refresh." message in your web app. console.log('New content is available; please refresh.'); } else { // At this point, everything has been precached. // It's the perfect time to display a // "Content is cached for offline use." message. console.log('Content is cached for offline use.'); } } }; }; }) .catch(error => { console.error('Error during service worker registration:', error); }); } function checkValidServiceWorker(swUrl) { // Check if the service worker can be found. If it can't reload the page. fetch(swUrl) .then(response => { // Ensure service worker exists, and that we really are getting a JS file. if ( response.status === 404 || response.headers.get('content-type').indexOf('javascript') === -1 ) { // No service worker found. Probably a different app. Reload the page. navigator.serviceWorker.ready.then(registration => { registration.unregister().then(() => { window.location.reload(); }); }); } else { // Service worker found. Proceed as normal. registerValidSW(swUrl); } }) .catch(() => { console.log( 'No internet connection found. App is running in offline mode.' ); }); } export function unregister() { if ('serviceWorker' in navigator) { navigator.serviceWorker.ready.then(registration => { registration.unregister(); }); } }