Skip to content

Commit 003aa1b

Browse files
Merge pull request #5 from kamleshchandnani/error-boundaries
Error Boundaries exercise and slides
2 parents 935da44 + 7a2810a commit 003aa1b

28 files changed

+526
-15
lines changed

exercises/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
"dependencies": {
88
"react": "16.2.0",
99
"react-dom": "16.2.0",
10+
"react-helmet": "^5.2.0",
1011
"react-router-dom": "^4.2.2",
11-
"react-scripts": "1.1.0"
12+
"react-scripts": "1.1.0",
13+
"styled-components": "^3.2.5"
1214
},
1315
"devDependencies": {},
1416
"scripts": {

exercises/src/App.js

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import React, { Component } from 'react';
2-
import {BrowserRouter as Router, Route, Link} from 'react-router-dom'
3-
import PerformanceOptimizations from './performance-optimizations'
1+
import React, { Component } from "react";
2+
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
3+
import PerformanceOptimizations from "./performance-optimizations";
4+
import ErrorBoundaries from "./error-boundaries";
45

56
class App extends Component {
67
render() {
@@ -9,13 +10,21 @@ class App extends Component {
910
<div className="container">
1011
<div className="sidebar">
1112
<ul>
12-
<li><Link to='/'>Refs</Link></li>
13-
<li><Link to='/performance-optimizations'>perfromance optimizations</Link></li>
13+
<li>
14+
<Link to="/">Refs</Link>
15+
</li>
16+
<li>
17+
<Link to="/performance-optimizations">perfromance optimizations</Link>
18+
</li>
19+
<li>
20+
<Link to="/error-boundaries">Error Boundaries</Link>
21+
</li>
1422
</ul>
1523
</div>
1624
<div className="content">
17-
<Route exact path='/' component={PerformanceOptimizations} />
18-
<Route path='/performance-optimizations' component={PerformanceOptimizations} />
25+
<Route exact path="/" component={PerformanceOptimizations} />
26+
<Route path="/performance-optimizations" component={PerformanceOptimizations} />
27+
<Route path="/error-boundaries" component={ErrorBoundaries} />
1928
</div>
2029
</div>
2130
</Router>
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
export const getRepos = username => {
2+
return fetch(`https://api.github.com/users/${username}/repos?sort=updated`)
3+
.then(response => response.json())
4+
.then(data => {
5+
let repos = data.map(repo => {
6+
return {
7+
id: repo.id,
8+
name: repo.name,
9+
stars: repo.stargazers_count,
10+
description: repo.description,
11+
url: repo.html_url
12+
};
13+
});
14+
repos = repos.sort((a, b) => b.stars - a.stars).slice(0, 5);
15+
return repos;
16+
})
17+
.catch(error => {
18+
/* Error handling */
19+
return {
20+
error
21+
};
22+
});
23+
};
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
export const getUser = username => {
2+
return fetch(`https://api.github.com/users/${username}`)
3+
.then(response => response.json())
4+
.then(data => {
5+
return {
6+
username: data.login,
7+
name: data.name,
8+
photo: data.avatar_url,
9+
bio: data.bio || "no description",
10+
url: data.html_url
11+
};
12+
})
13+
.catch(error => {
14+
return { error };
15+
});
16+
};
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import React from "react";
2+
import errorImage from "../../img/error.jpg";
3+
4+
const ErrorImage = () => <img alt="error" src={errorImage} />;
5+
6+
export default ErrorImage;
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import React from "react";
2+
import styled from "styled-components";
3+
4+
import A from "../library/anchor";
5+
import Blink from "../library/blink";
6+
7+
const Loading = styled(A)`
8+
background: #6ed396;
9+
width: 40%;
10+
height: 22px;
11+
margin-top: 10px;
12+
&::before {
13+
content: "x";
14+
}
15+
animation: ${Blink} 2s linear infinite;
16+
`;
17+
18+
export default props => {
19+
if (props.url) return <A href={props.url}>{props.children}</A>;
20+
else return <Loading />;
21+
};
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import React from "react";
2+
import githubLogo from "../../img/github-logo.png";
3+
const Logo = () => <img alt="github" src={githubLogo} />;
4+
5+
export default Logo;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import React from "react";
2+
import styled, { injectGlobal } from "styled-components";
3+
import Logo from "./logo";
4+
import Helmet from "react-helmet";
5+
6+
injectGlobal`
7+
body {
8+
margin: 0;
9+
padding: 0;
10+
background: #EEE;
11+
font-family: 'Nunito', sans-serif;
12+
}
13+
`;
14+
15+
const NavBar = styled.div`
16+
height: 30px;
17+
padding: 10px;
18+
background: #fff;
19+
border-bottom: 1px solid #ddd;
20+
text-align: center;
21+
> img {
22+
height: 30px;
23+
}
24+
`;
25+
26+
const Nav = () => (
27+
<NavBar>
28+
<Helmet
29+
title="react-error"
30+
link={[
31+
{
32+
href: "https://fonts.googleapis.com/css?family=Nunito",
33+
rel: "stylesheet"
34+
}
35+
]}
36+
/>
37+
<Logo />
38+
</NavBar>
39+
);
40+
41+
export default Nav;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import styled from "styled-components";
2+
3+
const A = styled.a`
4+
text-decoration: none;
5+
color: #6ed396;
6+
display: inline-block;
7+
width: "20px";
8+
`;
9+
10+
export default A;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import React from 'react'
2+
import styled from 'styled-components'
3+
4+
const Avatar = styled.span`
5+
display: inline-block;
6+
height: 100px;
7+
width: 100px;
8+
border-radius: 50%;
9+
border: 5px solid #EEE;
10+
background-color: #EEE;
11+
${props => (props.src ? `background-image: url(${props.src})` : '')};
12+
background-size: cover;
13+
`
14+
15+
export default props => <Avatar src={props.url} />
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { keyframes } from 'styled-components'
2+
3+
const Blink = keyframes`
4+
0% {opacity: 0.1}
5+
50% {opacity: 0.3}
6+
100% {opacity: 0.1}
7+
`
8+
9+
export default Blink
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import styled from "styled-components";
2+
3+
const Button = styled.button`
4+
background: #0eb550;
5+
color: #fff;
6+
border: 1px solid #1d99bd;
7+
border-radius: 2px;
8+
padding: 10px;
9+
margin-top: 20px;
10+
width: 100%;
11+
outline: none;
12+
font-size: 16px;
13+
&:active {
14+
background: #6ed396;
15+
}
16+
`;
17+
18+
export default Button;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import styled from 'styled-components'
2+
3+
const Card = styled.div`
4+
background: #FFF;
5+
border: 1px solid #DDD;
6+
border-radius: 2px;
7+
padding: 10px;
8+
`
9+
10+
export default Card
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import styled from 'styled-components'
2+
3+
const Clear = styled.div`
4+
clear: both;
5+
`
6+
7+
export default Clear
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import styled from "styled-components";
2+
3+
const Input = styled.input`
4+
background: #fff;
5+
border: 1px solid #ddd;
6+
border-radius: 2px;
7+
padding: 10px;
8+
width: calc(100% - 20px);
9+
outline: none;
10+
font-size: 16px;
11+
12+
&:hover,
13+
&:focus {
14+
border-color: #6ed396;
15+
}
16+
`;
17+
18+
export default Input;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import styled from "styled-components";
2+
3+
const Label = styled.div`
4+
height: 30px;
5+
padding: 10px;
6+
text-align: center;
7+
color: ${props => props.color || "#0EB550"};
8+
`;
9+
10+
export default Label;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import styled from 'styled-components'
2+
3+
const Star = styled.span`
4+
margin: 10px;
5+
&::after {
6+
content: ' \\2605';
7+
color: gold;
8+
}
9+
`
10+
11+
export default Star
53.9 KB
Loading
Loading
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import React, { Component } from "react";
2+
import Profile from "./modules/Profile";
3+
4+
class App extends Component {
5+
render() {
6+
return <Profile />;
7+
}
8+
}
9+
10+
export default App;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import React from 'react'
2+
import styled from 'styled-components'
3+
const Description = styled.div`
4+
color: #999;
5+
font-size: 12px;
6+
`
7+
8+
export default props => <Description>{props.content}</Description>
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import React, { Component, Fragment } from "react";
2+
import { getRepos } from "../../api/repos";
3+
import { getUser } from "../../api/user";
4+
import ProfileInput from "./profile-input";
5+
import UserProfile from "./profile";
6+
import Repositories from "./repositories";
7+
import Card from "../../components/library/card";
8+
import styled from "styled-components";
9+
10+
const RepositoriesCard = styled(Card)`
11+
text-align: center;
12+
box-sizing: border-box;
13+
margin: 20px auto 0;
14+
padding: 30px 50px;
15+
width: 500px;
16+
min-height: 100px;
17+
color: #000000;
18+
19+
@media (max-width: 600px) {
20+
width: 90%;
21+
}
22+
`;
23+
export default class Profile extends Component {
24+
state = {
25+
userRepos: [{}, {}, {}, {}, {}],
26+
userProfile: {}
27+
};
28+
getUserInfo = userName => {
29+
getUser(userName).then(userProfile => this.setState({ userProfile }));
30+
getRepos(userName).then(userRepos => this.setState({ userRepos }));
31+
};
32+
render() {
33+
const { userRepos, userProfile } = this.state;
34+
let RepositoriesData = (
35+
<RepositoriesCard>
36+
<UserProfile userProfile={userProfile} />
37+
<Repositories repos={userRepos} />
38+
</RepositoriesCard>
39+
);
40+
41+
if (!userProfile.url) {
42+
RepositoriesData = <RepositoriesCard>No Data Found..</RepositoriesCard>;
43+
}
44+
return (
45+
<Fragment>
46+
<ProfileInput getUserInfo={this.getUserInfo} />
47+
{RepositoriesData}
48+
</Fragment>
49+
);
50+
}
51+
}

0 commit comments

Comments
 (0)