I'am building a blog website with React ,and in the home page we can find list of posts,when the user clicks on the post he can see and read the post and comments etc...,i think the idea is just like this website (stackoverflow) where u can see a list of questions and hence u click one of them u will see the full question.
At this moment everything is well but hence i refresh the page data lost ,for that i tried to use local-storage,after i used local-stortage i refresh the page => the data persist and that's good.
And now the problem is when i back to the home page and click on another post it shows the same post every time and that's because of the local storage which not updating.
My Question: how can i update the local storage hence i click other post.
and the code is bleow:
Home.js:
import './Home.css';
import {Link} from 'react-router-dom';
import {Button} from 'react-bootstrap';
import Posts from '../Posts/Posts';
class Home extends React.Component{
constructor(props){
super(props);
this.state={
arrayposts:[],
}
}
getposts=()=>{
fetch('http://localhost:3002/')
.then(response=>response.json())
.then(data=>{
console.log(data)
this.setState({arrayposts:data});
}).catch(err=>console.log("can't get posts"))
}
componentDidMount(){
this.getposts();
}
render()
{
const {arrayposts}=this.state;
return(
<div >
<div className='topquestion' >
<h4>Top Questions</h4>
<Link to={'/Askquestion'}><Button id='askbtn'>Ask Question</Button></Link>
</div>
{
arrayposts.map((post,i)=>{
return (
<Posts
key={i}
postcontent={arrayposts[i].postcontent}
postid={arrayposts[i].id}
title={arrayposts[i].title}
postdate={arrayposts[i].postdate}
/>
);
})
}
</div>
);
}
}
export default Home;
Post.js:
import React from 'react';
import './Posts.css';
import {Link} from 'react-router-dom';
class Posts extends React.Component{
constructor(props){
super(props);
this.state={
title:this.props.title,
postid:this.props.postid,
content:this.props.postcontent,
postdate:this.props.postdate
}
}
render()
{
const {postcontent,title,postdate,postid}=this.props
return(
<div className='post'>
<Link id='title' to={{
pathname: "/Articles",
postcontent:postcontent,
postid:postid,
title:title
}}>{title} </Link>
<div className='reaction'>
<div id='like'><img alt='' src={require('./like.png')}width='24' height='24'/>reactions</div>
<div id='comment'><img alt='' src={require('./comment.png')}width='24' height='24'/>Add comment</div>
</div>
</div>
);
}
}
export default Posts;
Article.js:
import React from 'react';
import './Articles.css' ;
import {Link } from 'react-router-dom';
import localstorage from 'local-storage';
class Articles extends React.Component{
constructor(props){
super(props);
this.state={
title:'',
comment:'',
postid:this.props.location.postid,
arraycomments:[],
postcontent:this.props.location.postcontent
}
}
onchangecomment=(event)=>{
this.setState({comment:event.target.value});
}
addcomment=()=>{
fetch('http://localhost:3002/Addcomment',{
method:'post',
headers:{'Content-Type':'application/json'},
body:JSON.stringify({
comment:this.state.comment,
postid:this.state.postid
})
}).then(resposne=>{})
.catch(err=>{console.log('not added from the quesiotns')})
document.getElementById('txtarea').value='';
}
getcomments=()=>{
fetch('http://localhost:3002/getcomment',{
method:'post',
headers:{'Content-Type':'application/json'},
body:JSON.stringify({
postid:this.state.postid
})
})
.then(response=>response.json())
.then(response=>{
console.log(response)
this.setState({arraycomments:response})
})
.catch(err=>{console.log('not getting ')})
}
componentWillMount(){
localstorage.get('postid') && this.setState({postid:JSON.parse(localstorage.get('postid'))})
localstorage.get('postcontent') && this.setState({postcontent:JSON.parse(localstorage.get('postcontent'))})
localstorage.get('arraycomments') && this.setState({arraycomments:JSON.parse(localstorage.get('arraycomments'))})
localstorage.get('title') && this.setState({title:JSON.parse(localstorage.get('title'))})
}
componentDidMount(){
this.getcomments();
}
componentWillUpdate(nextProps,nextState){
localstorage.set('postid',JSON.stringify(nextState.postid));
localstorage.set('postcontent',JSON.stringify(nextState.postcontent));
localstorage.set('arraycomments',JSON.stringify(nextState.arraycomments));
localstorage.set('title',JSON.stringify(nextState.title));
}
render()
{
const {postcontent}=this.state;
return(
<div className='article'>
<div dangerouslySetInnerHTML={{ __html:postcontent }} />
<h4>Discussion</h4>
<div className='submitcommentform'>
<textarea id='txtarea' placeholder='Add discussion'
onChange={this.onchangecomment}
style={{height:'127px', width:'687px',padding:'6px 6px'}}>
</textarea>
<div className='submit-wrapper-actions'>
<Link to='' ><img className='wrapperimgage' src='https://practicaldev-herokuapp-com.freetls.fastly.net/assets/info-b2ce6a88ddd367e1416cd4c05aab2edee2d0b2c355d7b2aae1821eec48014e11.svg' height='21px'/></Link>
<Link to='' ><img className='wrapperimgage' src='https://practicaldev-herokuapp-com.freetls.fastly.net/assets/image-upload-f5242154f76102fa8869623b3d54adbeecbf24989ba8546e4f8ce229acec2c82.svg' height='21px'/></Link>
<button id='btnsubmit'onClick={this.addcomment}>Submit</button>
</div>
</div>
<div>
{
this.state.arraycomments.map((post,i)=>{
return (
<div className='commentsection' key={i}>{post.comm_content}</div>
);
})
}
</div>
</div>
);
}
}
export default Articles;
I hope that my question is clear.
Related
learning on Udemy part of the course work isnt working for me despite using the same codes as the video. The code should allow me to do a search based on username with option to go directly to the profile or a database of results. But I am getting Uncaught TypeError: this.props.history is undefined at main.js
Main.js
import React,{Component} from 'react';
import { BrowserRouter as Router,Route ,Routes} from 'react-router-dom';
class Main extends Component{
constructor(props){
super(props);
this.state={
Data:'',
checked:false
};
}
handleChange=(e)=>{
this.setState(()=>({
checked:!this.state.checked
}))
}
Search= (e)=> {
console.log(this.state.Data)
if(this.state.Data==='')return alert('Search field cannot be empty!')
if(this.state.checked){
this.props.history.push({
Pathname:`/Specific/${this.state.Data}`,
})
}else{
this.props.history.push({
Pathname:`/Data/${this.state.Data}`,
})
}
}
render(){
return(
<React.Fragment>
<section className="mainPage">
<center>
<div className="main" id="main">
<div className="container">
<div className="row">
<div className="col-lg-12 col-md-12">
<div className="main__text-container">
<h1 className="main__title">
GitFetch - Profile Finder for GitHub
</h1>
<p className="main__subtitle">
Check out the repos, followers and more, just by entering a username!
</p>
</div>
<div className="container">
<div className="check">
<input className="" type="checkbox" name="checked" onChange={this.handleChange} value={this.state.checked}/>
Go Direct to The user Profile
</div>
<input type="text" id="search" name="Data" className="btn btn-outline-primary"
placeholder={this.state.checked?'Go to user profile':'Enter username'}
onChange={(e)=>{this.setState({[e.target.name]:e.target.value})}}
value={this.state.Data}
/>
<span>
<button onClick={this.Search} className="btn btn-outline-primary">Search</button>
</span>
</div>
</div>
</div>
</div>
</div>
</center>
</section>
</React.Fragment>
);
}
}
export default Main;
App.js
import React,{Component} from 'react';
import './App.css';
import Nav from './components/nav/nav';
import Main from './components/github/main';
import { BrowserRouter as Router,Route ,Routes} from 'react-router-dom';
class App extends Component{
constructor(props){
super(props);
this.state={};
}
render(){
return(
<React.Fragment>
<Nav/>
<Router>
<Routes>
<Route exact path='/' element={<Main/>}/>
</Routes>
</Router>
</React.Fragment>
);
}
}
export default App;
changed code to
import React,{Component} from 'react';
import withRouter from '../withRouter';
class Main extends Component{
constructor(props){
super(props);
this.state={
Data:'',
checked:false
};
this.Search=this.Search.bind(this);
}
handleChange=(e)=>{
this.setState(()=>({
checked:!this.state.checked
}))
}
Search= (e)=> {
console.log(this.state.Data)
if(this.state.Data==='')return alert('Search field cannot be empty!')
if(this.state.checked){
this.props.history.push({
Pathname:`/Specific/${this.state.Data}`,
})
}else{
this.props.navigate({
Pathname:`/Data/${this.state.Data}`,
})
}
}
but i am still unable to redirect users to the specified path with this.props.navigate({
Pathname:/Data/${this.state.Data},
})
your props are empty and don't have instance of history , to provide history instance you need to wrap your component with export default withRouter(Main)
but withRouter has been deprecated in react-router-dom v6 so if you are using this version or above then kindly write a HOC for withRouter
here is a reference to use withRouter for v6 and above version of react-router-dom
https://github.com/remix-run/react-router/issues/7256
i am new to react and have been trying this for a long time without any success. Maybe someone could look through and determine the mistate i am making. here is my code.
I have the App.js file with a route to services page where i want to fecth and display data divs with services from a mysql database with react and JSX.
import React, { Component } from "react";
import { BrowserRouter } from "react-router-dom";
import Footer from "./Footer";
import Header from "./Header";
import axios from "axios";
class Services extends React.Component {
constructor(props) {
super(props);
this.state = {
services: [],
};
}
componentDidMount() {
axios
.get("http://localhost:5000/services")
.then((response) => this.setState({ services: response.data }));
}
render() {
var { services } = this.state;
return (
<div>
<div className="row">
<BrowserRouter>
<Header></Header>
</BrowserRouter>
<div className="Services">
<br></br>
<br></br>
<br></br>
</div>
<div className="row">
<h1 className="text-center title">Our Services</h1>
<p className="p-3 text-left">
Quickly get help for your issue by selcting the service that
matches your issues. You can always describe your issue if it does
not match any of our services and you only pay when the issue has
been resolved.
</p>
<hr></hr>
{services}
</div>
</div>
<BrowserRouter>
<Footer></Footer>
</BrowserRouter>
</div>
);
}
}
export default Services;
import React from "react";
import { BrowserRouter } from "react-router-dom";
import axios from "axios";
class Services extends React.Component {
constructor(props) {
super(props);
this.state = {
data: []
};
}
componentDidMount() {
axios.get("https://jsonplaceholder.typicode.com/posts").then(response => {
console.log(response);
this.setState({ data: response.data });
});
}
render() {
let services_data = [];
this.state.data.forEach((res, i) => {
services_data.push(
<ul key={res.i}>
<li>{res.id}</li>
<li>{res.title}</li>
<li>{res.body}</li>
</ul>
);
});
return (
<div>
<div className="row">
<BrowserRouter>Header</BrowserRouter>
<div className="Services" />
<div className="row">
<h1 className="text-center title">Our Services</h1>
<p className="p-3 text-left">
Quickly get help for your issue by selcting the service that
matches your issues. You can always describe your issue if it does
not match any of our services and you only pay when the issue has
been resolved.
</p>
<hr />
{services_data}
</div>
</div>
<BrowserRouter>Footer</BrowserRouter>
</div>
);
}
}
export default Services;
The above code is working fine and split the method like this.
I'm not getting props in my Nav component. Odd thing is, 'this.props.history.push' is working in my other components.
The same function is working in my other components, but when I try to call the push function, I'm getting 'err in logout TypeError: Cannot read property 'push' of undefined'. The 'this.props' object is logging as '{}'.
Any help is appreciated, thank you.
import React from 'react'
import logo from 'logo.png'
import css from './Nav.module.scss'
import { Link } from 'react-router-dom'
import Cookies from 'js-cookie'
import axios from 'axios'
class Nav extends React.Component {
constructor(props) {
super(props)
this.state = {
loggedIn: false
}
console.log(this.props)
}
_handleLogout = () => {
// const self = this
console.log(this.props)
axios.get('http://localhost:8080/logout', {
withCredentials: true
})
.then(res => {
console.log(res)
console.log('logout')
if (Cookies.get('sid') === undefined) {
this.props.history.push('/')
}
console.log(this.props)
})
.catch(err => {
console.log('err in logout', err)
})
}
render() {
return (
<div className={css.nav}>
<div className={css.leftPart}>
<Link to="/">
<div className={css.brandicon}>
<img src={logo} alt="Logo" />
</div>
<div className={css.brandname}>
somebrand
</div>
</Link>
</div>
<div className={css.rightPart}>
{
Cookies.get('sid') === undefined ?
<Link to="/login">
<div className={css.loginButton}>
Login
</div>
</Link>
:
<div className={css.logoutButton} onClick={this._handleLogout}>
Logout
</div>
}
</div>
</div>
)
}
}
export default Nav
My Nav component is only referenced once in my Layout component:
import React from 'react'
import Nav from 'components/Nav/Nav'
import css from './BasicLayout.module.scss'
class Basic extends React.Component {
render() {
return (
<div className={css.page}>
<Nav />
<div className={css.content}>
{this.props.children}
</div>
</div>
)
}
}
export default Basic
history and location are special props injected by React Router's HOC withRouter
import { withRouter } from 'react-router-dom'
class Nav extends React.Component{
render(){
const { history, location } = this.props
return <div>{`I'm at ${location.pathname}`}</div>
}
}
export default withRouter(Nav)
It works for functional components as well
export const Component = withRouter(({ history, location })) =>(
<div>{`I'm at ${location.pathname}`}</div>
)
I am trying to follow this tutorial to create a pagination in my application https://www.npmjs.com/package/react-js-pagination#usage . The pagination part works fine. How to create previousPageClick, nextPageClick functions for the course component so the page will display different set of records based on the page number? Thanks.
My App.js code:
import React, { Component } from 'react';
import './App.css';
import axios from 'axios';
import Pagination from "react-js-pagination";
require("bootstrap-less/bootstrap/pagination.less");
class App extends Component {
constructor() {
super();
this.state ={
courses:[],
activePage: 15
};
}
componentDidMount(){
axios.get('myURL')
.then(response=>{
this.setState({courses:response.data});
});
}
handlePageChange(pageNumber) {
this.setState({activePage: pageNumber});
}
render() {
const courses= this.state.courses.map(course=>(<Course ID={course.ID} coursename={course.coursetitle} />));
const totalCourses=courses.length;
return (
<div className="App">
<div className="pagination">
Total Classes: {totalCourses}
<Pagination
activePage={this.state.activePage}
itemsCountPerPage={100}
totalItemsCount={totalCourses}
pageRangeDisplayed={5}
onChange={this.handlePageChange.bind(this)}
/>
</div>
<div className="Course">Courses: {courses}
</div>
</div>
);
}
}
export default App;
ReactDOM.render(<App />, document.getElementById("root"));
Course.js
import React from 'react';
const course=props=>{
return(
<div className="Course">
<p>ID: {props.ID}</p>
<p>SUBJECT: {props.SUBJECT}</p>
</div>
);
}
export default course;
I am really new to React, so I am trying to build a Pokemon app. My main goal is to build the list of 20 pokemon, and detail box which when clicked on Pokemon from the list should display chosen pokemon details, pictures etc.
import React, { Component } from 'react';
import './styles/App.css';
class App extends Component{
render(){
return <div className="App">
<h1> Pokedex! </h1>
<PokemonList/>
<PokemonDetail/>
</div>;
}
}
class Pokemon extends Component {
render(){
const {pokemon,id} = this.props;
return <div className="pokemon--species">
<button className="pokemon--species--container">
<div className="pokemon--species--sprite">
<img src={`https://pokeapi.co/media/sprites/pokemon/${id}.png`} />
</div>
<div className="pokemon--species--name">{id} {pokemon.name} {pokemon.url} </div>
</button>
</div>;
}
}
class PokemonDetail extends Component {
render(){
const {pokemon, id} = this.props;
return <div className="pokemon--species">
<button className="pokemon--species--container">
<div className="pokemon--species--sprite">
<img src={`https://pokeapi.co/media/sprites/pokemon/${id}.png`} />
</div>
<div className="pokemon--species--name">{id}</div>
<p>Attack:72</p>
<p>Defense:23</p>
<p>Health:99</p>
</button>
</div>;
}
}
class PokemonList extends Component{
constructor(props){
super(props);
this.state = {
species : [],
fetched : false,
loading : false,
};
}
componentWillMount(){
this.setState({
loading : true
});
fetch('https://pokeapi.co/api/v2/pokemon?limit=20').then(res=>res.json())
.then(response=>{
this.setState({
species : response.results,
loading : true,
fetched : true
});
});
}
render(){
const {fetched, loading, species} = this.state;
let content ;
if(fetched){
content = <div className="pokemon--species--list">{
species.map((pokemon,index) => <Pokemon key={pokemon.name} id={index+1} pokemon={pokemon}/>)
}
</div>;
}else if(loading && !fetched){
content = <p> Loading ...</p>;
}
else{
content = <div/>;
}
return <div className="container">
{content}
</div>;
}
}
export default App;
I know, there is much to do there, but first I want to understand how to pass ID to pokemondetails class.
Have a look at react-router and how to pass parameters to components associated with routes. Basically, you could have two routes that would render following components PokemonList and PokemonDetail. Redirect user from the PokemonList to PokemonDetail and append pokemonId to the url ( e.g "/details/23").
After redirection 'PokemonDetail' component would be rendered and pokemonId would be available in the component.
const App = () => (
<Router>
<div>
...
<Route exact path="/" component={PokemonList}/>
<Route path="/details/:pokemonId" component={PokemonDetail}/>
</div>
</Router>
)
// access pokemonId
class PokemonDetail extends Component{
render() {
return (
<div>
<h2>{this.props.params.pokemonId}</h2>
</div>
)
}
}