├── App.js
├── README.md
├── app.json
├── babel.config.js
├── index.js
├── metro.config.js
├── package-lock.json
├── package.json
└── src
├── .DS_Store
├── component
├── dataItem.js
├── modal.js
└── time.js
├── config
└── rest_consfig.js
├── screens
├── TabScreen.js
└── tabs
│ ├── tab1.js
│ ├── tab2.js
│ └── tab3.js
└── service
└── news.js
/App.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Sample React Native App
3 | * https://github.com/facebook/react-native
4 | *
5 | * @format
6 | * @flow
7 | */
8 |
9 | import React, {Component} from 'react';
10 | import TabScreen from './src/screens/TabScreen';
11 |
12 | export default class App extends Component {
13 | render() {
14 | return (
15 |
16 | );
17 | }
18 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React Native News App
2 |
3 | This is a react native project created for tutorial purpose by **Pradip Debnath** for his [YouTube channel](https://www.youtube.com/user/itzpradip).
4 |
5 | I have used NewsAPI.Org to fetch the news and NativeBase.io to build the UI of the app. You can [check full tutorial series here](https://www.youtube.com/playlist?list=PLQWFhX-gwJbl5sIXMZvdvGYCcZbUevE88).
6 |
7 | ##Screenshot
8 | 
--------------------------------------------------------------------------------
/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "newsApp",
3 | "displayName": "newsApp"
4 | }
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ['module:metro-react-native-babel-preset'],
3 | };
4 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @format
3 | */
4 |
5 | import {AppRegistry} from 'react-native';
6 | import App from './App';
7 | import {name as appName} from './app.json';
8 |
9 | AppRegistry.registerComponent(appName, () => App);
10 |
--------------------------------------------------------------------------------
/metro.config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Metro configuration for React Native
3 | * https://github.com/facebook/react-native
4 | *
5 | * @format
6 | */
7 |
8 | module.exports = {
9 | transformer: {
10 | getTransformOptions: async () => ({
11 | transform: {
12 | experimentalImportSupport: false,
13 | inlineRequires: false,
14 | },
15 | }),
16 | },
17 | };
18 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "newsApp",
3 | "version": "0.0.1",
4 | "private": true,
5 | "scripts": {
6 | "start": "node node_modules/react-native/local-cli/cli.js start",
7 | "test": "jest"
8 | },
9 | "dependencies": {
10 | "moment": "^2.24.0",
11 | "native-base": "^2.12.1",
12 | "react": "16.8.3",
13 | "react-native": "0.59.8"
14 | },
15 | "devDependencies": {
16 | "@babel/core": "7.4.5",
17 | "@babel/runtime": "7.4.5",
18 | "babel-jest": "24.8.0",
19 | "jest": "24.8.0",
20 | "metro-react-native-babel-preset": "0.54.1",
21 | "react-test-renderer": "16.8.3"
22 | },
23 | "jest": {
24 | "preset": "react-native"
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/itzpradip/react-native-newsApp/b4ea41d6f292d0347e5256469b040d2c15b06ff0/src/.DS_Store
--------------------------------------------------------------------------------
/src/component/dataItem.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import { ListItem, Left, Right, Thumbnail, Body, View, Text, Button } from 'native-base';
3 | import TimeAgo from './time';
4 |
5 | class DataItem extends Component {
6 |
7 | constructor(props) {
8 | super(props);
9 | this.data = props.data;
10 | }
11 |
12 | handlePress = () => {
13 | const {url, title} = this.data;
14 | this.props.onPress({url, title});
15 | }
16 |
17 | render() {
18 | return(
19 |
20 |
21 |
22 |
23 |
24 | {this.data.title}
25 | {this.data.description}
26 |
27 | {this.data.source.name}
28 |
29 |
30 |
31 |
32 |
35 |
36 |
37 | );
38 | }
39 | }
40 |
41 | export default DataItem;
--------------------------------------------------------------------------------
/src/component/modal.js:
--------------------------------------------------------------------------------
1 | //import libraries
2 | import React, { Component } from 'react';
3 | import { Dimensions, WebView, Modal, Share } from 'react-native';
4 | import {Container, Header, Content, Body, Left, Icon, Right, Title, Button} from 'native-base';
5 |
6 | const webViewHeight = Dimensions.get('window').height - 56;
7 |
8 | // create a component
9 | class ModalComponent extends Component {
10 |
11 | constructor(props) {
12 | super(props);
13 | }
14 |
15 | handleClose = () => {
16 | return this.props.onClose();
17 | }
18 |
19 | handleShare = () => {
20 | const {url, title} = this.props.articleData;
21 | message = `${title}\n\nRead More @${url}\n\nShared via RN News App`;
22 | return Share.share(
23 | {title, message, url: message},
24 | {dialogTitle:`Share ${title}`}
25 | );
26 | }
27 |
28 | render() {
29 | const { showModal, articleData } = this.props;
30 | const { url } = articleData;
31 | if( url != undefined ) {
32 | return (
33 |
39 |
40 |
41 |
42 |
45 |
46 |
47 |
48 |
49 |
50 |
53 |
54 |
55 |
56 |
60 |
61 |
62 |
63 | );
64 | } else {
65 | return null;
66 | }
67 | }
68 | }
69 |
70 | //make this component available to the app
71 | export default ModalComponent;
72 |
--------------------------------------------------------------------------------
/src/component/time.js:
--------------------------------------------------------------------------------
1 | //import libraries
2 | import React, { Component } from 'react';
3 | import { Text } from 'native-base';
4 | import moment from 'moment';
5 |
6 | // create a component
7 | class Time extends Component {
8 |
9 | constructor(props) {
10 | super(props);
11 | this.date = props.time;
12 | }
13 |
14 | render() {
15 | const time = moment( this.date || moment.now() ).fromNow();
16 | return (
17 | {time}
18 | );
19 | }
20 | }
21 |
22 | //make this component available to the app
23 | export default Time;
24 |
--------------------------------------------------------------------------------
/src/config/rest_consfig.js:
--------------------------------------------------------------------------------
1 | export const articles_url = 'https://newsapi.org/v2/top-headlines';
2 | export const country_code = 'in';
3 | export const category = 'general';
4 | export const _api_key = 'YOUR_API_KEY';
5 |
--------------------------------------------------------------------------------
/src/screens/TabScreen.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Container, Header, Content,Left, Body, Right, Title, Tab, Tabs } from 'native-base';
3 | import Tab1 from './tabs/tab1';
4 | import Tab2 from './tabs/tab2';
5 | import Tab3 from './tabs/tab3';
6 | export default class TabsExample extends Component {
7 | render() {
8 | return (
9 |
10 |
11 |
12 |
13 | News App
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | );
30 | }
31 | }
--------------------------------------------------------------------------------
/src/screens/tabs/tab1.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Alert, View, ActivityIndicator } from 'react-native';
3 | import { Container, Content, List, Text } from 'native-base';
4 |
5 | import DataItem from '../../component/dataItem';
6 | import Modal from '../../component/modal';
7 |
8 | import { getArticles } from '../../service/news';
9 |
10 | export default class ListThumbnailExample extends Component {
11 |
12 | constructor(props) {
13 | super(props);
14 |
15 | this.state = {
16 | isLoading: true,
17 | data: null,
18 | setModalVisible: false,
19 | modalArticleData: {}
20 | }
21 | }
22 |
23 | handleItemDataOnPress = (articleData) => {
24 | this.setState({
25 | setModalVisible: true,
26 | modalArticleData: articleData
27 | });
28 | }
29 |
30 | handleModalClose = () => {
31 | this.setState({
32 | setModalVisible: false,
33 | modalArticleData: {}
34 | });
35 | }
36 |
37 | componentDidMount() {
38 | getArticles().then(data => {
39 | this.setState({
40 | isLoading: false,
41 | data: data
42 | });
43 | }, error => {
44 | Alert.alert('Error', 'Something went wrong!');
45 | }
46 | )
47 | }
48 |
49 | render() {
50 | console.log(this.state.data);
51 |
52 | let view = this.state.isLoading ? (
53 |
54 |
55 |
56 |
57 | ) : (
58 | {
61 | return (
62 |
63 | )
64 | }} />
65 | )
66 |
67 | return (
68 |
69 |
70 | {view}
71 |
72 |
77 |
78 | );
79 | }
80 | }
--------------------------------------------------------------------------------
/src/screens/tabs/tab2.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Alert, View, ActivityIndicator } from 'react-native';
3 | import { Container, Content, List, Text } from 'native-base';
4 |
5 | import DataItem from '../../component/dataItem';
6 | import Modal from '../../component/modal';
7 |
8 | import { getArticles } from '../../service/news';
9 |
10 | export default class Tab2 extends Component {
11 |
12 | constructor(props) {
13 | super(props);
14 |
15 | this.state = {
16 | isLoading: true,
17 | data: null,
18 | setModalVisible: false,
19 | modalArticleData: {}
20 | }
21 | }
22 |
23 | handleItemDataOnPress = (articleData) => {
24 | this.setState({
25 | setModalVisible: true,
26 | modalArticleData: articleData
27 | });
28 | }
29 |
30 | handleModalClose = () => {
31 | this.setState({
32 | setModalVisible: false,
33 | modalArticleData: {}
34 | });
35 | }
36 |
37 | componentDidMount() {
38 | getArticles('business').then(data => {
39 | this.setState({
40 | isLoading: false,
41 | data: data
42 | });
43 | }, error => {
44 | Alert.alert('Error', 'Something went wrong!');
45 | }
46 | )
47 | }
48 |
49 | render() {
50 | console.log(this.state.data);
51 |
52 | let view = this.state.isLoading ? (
53 |
54 |
55 |
56 |
57 | ) : (
58 | {
61 | return (
62 |
63 | )
64 | }} />
65 | )
66 |
67 | return (
68 |
69 |
70 | {view}
71 |
72 |
77 |
78 | );
79 | }
80 | }
--------------------------------------------------------------------------------
/src/screens/tabs/tab3.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Alert, View, ActivityIndicator } from 'react-native';
3 | import { Container, Content, List, Text } from 'native-base';
4 |
5 | import DataItem from '../../component/dataItem';
6 | import Modal from '../../component/modal';
7 |
8 | import { getArticles } from '../../service/news';
9 |
10 | export default class Tab3 extends Component {
11 |
12 | constructor(props) {
13 | super(props);
14 |
15 | this.state = {
16 | isLoading: true,
17 | data: null,
18 | setModalVisible: false,
19 | modalArticleData: {}
20 | }
21 | }
22 |
23 | handleItemDataOnPress = (articleData) => {
24 | this.setState({
25 | setModalVisible: true,
26 | modalArticleData: articleData
27 | });
28 | }
29 |
30 | handleModalClose = () => {
31 | this.setState({
32 | setModalVisible: false,
33 | modalArticleData: {}
34 | });
35 | }
36 |
37 | componentDidMount() {
38 | getArticles('technology').then(data => {
39 | this.setState({
40 | isLoading: false,
41 | data: data
42 | });
43 | }, error => {
44 | Alert.alert('Error', 'Something went wrong!');
45 | }
46 | )
47 | }
48 |
49 | render() {
50 | console.log(this.state.data);
51 |
52 | let view = this.state.isLoading ? (
53 |
54 |
55 |
56 |
57 | ) : (
58 | {
61 | return (
62 |
63 | )
64 | }} />
65 | )
66 |
67 | return (
68 |
69 |
70 | {view}
71 |
72 |
77 |
78 | );
79 | }
80 | }
--------------------------------------------------------------------------------
/src/service/news.js:
--------------------------------------------------------------------------------
1 | import { articles_url, _api_key, country_code } from '../config/rest_consfig';
2 |
3 | export async function getArticles(category='general') {
4 |
5 | try {
6 | let articles = await fetch(`${articles_url}?country=${country_code}&category=${category}`, {
7 | headers: {
8 | 'X-API-KEY': _api_key
9 | }
10 | });
11 |
12 | let result = await articles.json();
13 | articles = null;
14 |
15 | return result.articles;
16 | }
17 | catch(error) {
18 | throw error;
19 | }
20 | }
--------------------------------------------------------------------------------