THAPA TECHNICAL

HOUSE OF WEB DEVELOPERS AND TECHNOLOGY.

Tech News Website using React JS

 Tech News Website using React JS







App.js File

import Pagination from "./Pagination";
import Search from "./Search";
import Stories from "./Stories";
import "./App.css";

const App = () => {
  return (
    <>
      <Search />
      <Pagination />
      <Stories />
    </>
  );
};

export default App;



Context.js File 


// context  creation ✅
// provider ✅
// consumer lenghty remove useContext hook
// useContext hook ✅

import React, { useContext, useReducer, useEffect } from "react";
import reducer from "./reducer";

let API = "https://hn.algolia.com/api/v1/search?";

const initialState = {
  isLoading: true,
  query: "CSS",
  nbPages: 0,
  page: 0,
  hits: [],
};

const AppContext = React.createContext();

// to create a provider fucntion
const AppProvider = ({ children }) => {
  // const [state, setstate] = useState(initialState);

  const [state, dispatch] = useReducer(reducer, initialState);

  const fecthApiData = async (url) => {
    dispatch({ type: "SET_LOADING" });

    try {
      const res = await fetch(url);
      const data = await res.json();
      console.log(data);
      dispatch({
        type: "GET_STORIES",
        payload: {
          hits: data.hits,
          nbPages: data.nbPages,
        },
      });
      // isLoading = false;
    } catch (error) {
      console.log(error);
    }
  };

  // to remove the post
  const removePost = (post_ID) => {
    dispatch({ type: "REMOVE_POST", payload: post_ID });
  };

  // plz subscribe thapa technical youtube channel

  // search
  const searchPost = (searchQuery) => {
    dispatch({
      type: "SEARCH_QUERY",
      payload: searchQuery,
    });
  };

  // pagination
  const getNextPage = () => {
    dispatch({
      type: "NEXT_PAGE",
    });
  };

  const getPrevPage = () => {
    dispatch({
      type: "PREV_PAGE",
    });
  };

  // to call teh api func
  useEffect(() => {
    fecthApiData(`${API}query=${state.query}&page=${state.page}`);
  }, [state.query, state.page]);

  return (
    <AppContext.Provider
      value={{ ...state, removePost, searchPost, getNextPage, getPrevPage }}>
      {children}
    </AppContext.Provider>
  );
};

// custom hook chitsreate
const useGlobalContext = () => {
  return useContext(AppContext);
};

export { AppContext, AppProvider, useGlobalContext };



Stories.js File

import React from "react";
import { useGlobalContext } from "./context";

const Stories = () => {
  const { hits, isLoading, removePost } = useGlobalContext();
  if (isLoading) {
    return (
      <>
        <h1>Loading.....</h1>
      </>
    );
  }
  return (
    <>
      <div className="stories-div">
        {hits.map((curPost) => {
          const { title, author, objectID, url, num_comments } = curPost;
          return (
            <div className="card" key={objectID}>
              <h2>{title}</h2>
              <p>
                By <span> {author}</span> | <span> {num_comments} </span>
                comments
              </p>
              <div className="card-button">
                <a href={url} target="_blank">
                  Read More
                </a>
                <a href="#" onClick={() => removePost(objectID)}>
                  Remove
                </a>
              </div>
            </div>
          );
        })}
      </div>
    </>
  );
};

export default Stories;



App.css File

@import url("https://fonts.googleapis.com/css2?family=IBM+Plex+Serif:wght@400&family=Poppins:wght@400;600&display=swap");

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: "Poppins", sans-serif;
}

html {
  font-size: 62.5%;
}

body {
  background-color: rgb(219, 230, 253);
}

h1 {
  font-size: 3.2rem;
  margin: 2rem 0;
  text-align: center;
}

h2 {
  font-family: "IBM Plex Serif", serif;
  font-size: 2.4rem;
}

p {
  margin: 2rem 0;
  color: rgba(21, 19, 60, 0.5);
  font-weight: 400;
  font-size: 1.6rem;
  display: inline-block;
}

span {
  text-transform: capitalize;
  font-weight: bold;
}

.stories-div {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  gap: 4rem;
}

.card {
  min-width: 20rem;
  width: 40vw;
  padding: 4rem;
  background-color: #ffffff;
  box-shadow: rgba(100, 100, 111, 0.2) 0px 7px 29px 0px;
  border-radius: 0.5rem;
  color: #15133c;
}

.card-button {
  flex-direction: row;
  width: 100%;
  display: flex;
  justify-content: space-between;
}

.card-button a {
  color: #92b4ec;
  font-weight: 400;
  font-size: 1.6rem;
}

.card-button a:last-child {
  color: red;
}

form {
  display: grid;
  place-items: center;
}

// subscribe to Thapa Technical YouTube
// channel for more awesome videos 😀

input {
  padding: 1rem;
  min-width: 40rem;
  font-size: 2rem;
  text-transform: capitalize;
  border: none;
  border-bottom: 0.2rem solid #15133c;
  outline: none;
}

.pagination-btn {
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

button {
  padding: 0.8rem 2.2rem;
  border: none;
  font-size: 1.6rem;
  background-color: #15133c;
  color: #ffffff;
  margin: 3rem;
  cursor: pointer;
  display: inline-block;
}

/* responsive layout  */

@media (max-width: 998px) {
  html {
    font-size: 56%;
  }

  .card {
    min-width: 45rem;
    padding: 2.5rem;
  }
}

@media (max-width: 768px) {
  html {
    font-size: 51%;
  }

  .card {
    min-width: 35rem;
    padding: 2rem;
  }
}



Search.js File


import React from "react";
import { useGlobalContext } from "./context";

const Search = () => {
  const { query, searchPost } = useGlobalContext();
  return (
    <>
      <h1>Thapa Technical Tech Website</h1>
      <form onSubmit={(e) => e.preventDefault()}>
        <div>
          <input
            type="text"
            placeholder="search here"
            value={query}
            onChange={(e) => searchPost(e.target.value)}
          />
        </div>
      </form>
    </>
  );
};

export default Search;



Pagination.js File


import React from "react";
import { useGlobalContext } from "./context";

const Pagination = () => {
  const { page, nbPages, getPrevPage, getNextPage } = useGlobalContext();
  return (
    <>
      <div className="pagination-btn">
        <button onClick={() => getPrevPage()}>PREV</button>
        <p>
          {page + 1} of {nbPages}
        </p>
        <button onClick={() => getNextPage()}>NEXT</button>
      </div>
    </>
  );
};

export default Pagination;




Reducer.js File


const reducer = (state, action) => {
  switch (action.type) {
    case "SET_LOADING":
      return {
        ...state,
        isLoading: true,
      };
    case "GET_STORIES":
      return {
        ...state,
        isLoading: false,
        hits: action.payload.hits,
        nbPages: action.payload.nbPages,
      };
    case "REMOVE_POST":
      return {
        ...state,
        hits: state.hits.filter(
          (curElem) => curElem.objectID !== action.payload
        ),
      };
    case "SEARCH_QUERY":
      return {
        ...state,
        query: action.payload,
      };

    case "NEXT_PAGE":
      let pageNumInc = state.page + 1;

      if (pageNumInc >= state.nbPages) {
        pageNumInc = 0;
      }
      return {
        ...state,
        page: pageNumInc,
      };

    case "PREV_PAGE":
      let pageNum = state.page - 1;

      if (pageNum <= 0) {
        pageNum = 0;
      }

      return {
        ...state,
        page: pageNum,
      };
   
    // you can add the default case too
  }

  return state;
};

export default reducer;



4 comments:

  1. QuickBooks is best option for your managing business Financial Task . This Software also provide best Customer Service for any query so please call at
    Quickbooks Support Phone Number .+1 602-325-1557

    ReplyDelete
  2. Our customers’ semantic management needs so they can. Also if any need to view interior designs.this is posted by Jayamm Digital Marketing in chennai Digital Marketing Agency in chennai,
    Interior Designer in chennai
    Best Interior Designer in chennai
    https://www.gshome.in/
    https://jayamm.com/

    ReplyDelete
  3. Nice content, Best millets and rice through online with low price. Bamboo Rice. ogranny farms

    ReplyDelete
  4. After I initially commented I seem to have clicked on the -Notify me when new comments are added- checkbox and now every time a comment is added I receive 4 emails with the exact same comment. There has to be an easy method you are able to remove me from that service? Kudos!
    https://www.webranksindia.com/

    ReplyDelete