React router not rendered with second click












1















I use Router like the code below to switch between components includes Home, Sidebar, Detail, Category.



For the first load, It will display all recent posts, featured posts.
When I click a post to go detail It work well.
In detail page, I click to render new post but It does not render.



My code:



class App extends React.Component {
render () {
// if ('serviceWorker' in navigator) {
// const registration = runtime.register();
// }
module.hot.accept();
$("body").removeClass();
$("body").addClass("homepage");
<Helmet>
<title>{blog_title}</title>
<meta name="description" content={blog_description} />
</Helmet>
const {feature, main, sidebar, mainbottom, header } = this.props;
return (
<div id="all">
{header}
<div className="container">
<div className="main-feature" id="main-feature">
{feature}
</div>
</div>
<div id="content" className="site-content">
<div className="container">
<div className="divcontainer">
<div id="po-homepage" className="content-area">
{main}
</div>
<aside id="secondary" className="sidebar widget-area">
<div className="popular_post" id="popular_post">
{sidebar}
</div>
</aside>
</div>
</div>
</div>
<div className="cat-list">
<div className="container">
<div className="thecategories" id="thecategories">
{mainbottom}
</div>
</div>
</div>
</div>
)
}
}


Please see photo:



enter image description here



My detail post:



import React, {Component} from "react"; //nếu chỉ import React thì sẽ cần React.Component
import $ from 'jquery';
import { Helmet } from "react-helmet";
import {
BrowserRouter as Router,
Route,
Switch
} from 'react-router-dom';

class Detail extends React.Component {
constructor(props) {
super(props);
this.state = {
post: {}
};
}

componentDidMount() {

//scroll to detail
$(document).ready(function(){
$("html, body").animate({ scrollTop: $("#content").offset().top - 100 }, 500);
$("body").removeClass();
$("body").addClass("detailpage");
});

console.log(this.props.detailink);

var that = this;
var url = window.location.href.split("/");
var slug = url.pop() || url.pop();
// console.log(CelestialSettings.URL.api + "/posts?slug=" + slug);
fetch(CelestialSettings.URL.api + "/posts?slug=" + slug)
.then(function(response) {
if (!response.ok) {
throw Error(response.statusText);
}
return response.json();
})
.then(function(res) {
that.setState({ post: res[0] });
});
}

renderPosts() {
return (
<div className="card">
<div className="card-body">
<Helmet>
<title>{this.state.post.title.rendered}</title>
<meta name="description" content={this.state.post.excerpt.rendered.replace(/</?[^>]+(>|$)/g, "")} />
</Helmet>
<h1 className="card-title">{this.state.post.title.rendered}</h1>
<p className="card-text">
<small className="text-muted">
{this.state.post.author_name} &ndash;{" "}
{this.state.post.published_date}
</small>
</p>
{this.state.post.featured_image_src ? (
<img
className="featured-image"
src={this.state.post.featured_image_src}
alt="featured image"
/>
) : null}
<p
className="card-text"
dangerouslySetInnerHTML={{
__html: this.state.post.content.rendered
}}
/>
</div>
</div>
);
}

renderEmpty() {
return (
<div></div>
);
}

render() {
var href = window.location.href+"/?view=react";
return (
<div className="container post-entry">
{this.state.post.title ? this.renderPosts() : this.renderEmpty()}
</div>
);
}
}

export default Detail;


As I added ComponentDidUpdate(), it works but it renders loop back top first detail before render new post. I use like this.



componentDidUpdate() {

var that = this;
var url = window.location.href.split("/");
var slug = url.pop() || url.pop();
console.log(CelestialSettings.URL.api + "/posts?slug=" + slug);
fetch(CelestialSettings.URL.api + "/posts?slug=" + slug)
.then(function(response) {
if (!response.ok) {
throw Error(response.statusText);
}
return response.json();
})
.then(function(res) {
that.setState({ post: res[0] });
});
}


Any suggestion for my issue? Thank you so much.










share|improve this question

























  • is your <Detail> component exported with withRouter

    – Gabriele Petrioli
    Nov 19 '18 at 14:11











  • @GabrielePetrioli I do not know it. Can you explain me?

    – Hai Tien
    Nov 19 '18 at 14:11











  • Please show the code with your Detail component.

    – Gabriele Petrioli
    Nov 19 '18 at 14:17











  • @GabrielePetrioli Thank you so much. I updated detail component

    – Hai Tien
    Nov 19 '18 at 14:18











  • Added answer with a solution.

    – Gabriele Petrioli
    Nov 19 '18 at 14:23
















1















I use Router like the code below to switch between components includes Home, Sidebar, Detail, Category.



For the first load, It will display all recent posts, featured posts.
When I click a post to go detail It work well.
In detail page, I click to render new post but It does not render.



My code:



class App extends React.Component {
render () {
// if ('serviceWorker' in navigator) {
// const registration = runtime.register();
// }
module.hot.accept();
$("body").removeClass();
$("body").addClass("homepage");
<Helmet>
<title>{blog_title}</title>
<meta name="description" content={blog_description} />
</Helmet>
const {feature, main, sidebar, mainbottom, header } = this.props;
return (
<div id="all">
{header}
<div className="container">
<div className="main-feature" id="main-feature">
{feature}
</div>
</div>
<div id="content" className="site-content">
<div className="container">
<div className="divcontainer">
<div id="po-homepage" className="content-area">
{main}
</div>
<aside id="secondary" className="sidebar widget-area">
<div className="popular_post" id="popular_post">
{sidebar}
</div>
</aside>
</div>
</div>
</div>
<div className="cat-list">
<div className="container">
<div className="thecategories" id="thecategories">
{mainbottom}
</div>
</div>
</div>
</div>
)
}
}


Please see photo:



enter image description here



My detail post:



import React, {Component} from "react"; //nếu chỉ import React thì sẽ cần React.Component
import $ from 'jquery';
import { Helmet } from "react-helmet";
import {
BrowserRouter as Router,
Route,
Switch
} from 'react-router-dom';

class Detail extends React.Component {
constructor(props) {
super(props);
this.state = {
post: {}
};
}

componentDidMount() {

//scroll to detail
$(document).ready(function(){
$("html, body").animate({ scrollTop: $("#content").offset().top - 100 }, 500);
$("body").removeClass();
$("body").addClass("detailpage");
});

console.log(this.props.detailink);

var that = this;
var url = window.location.href.split("/");
var slug = url.pop() || url.pop();
// console.log(CelestialSettings.URL.api + "/posts?slug=" + slug);
fetch(CelestialSettings.URL.api + "/posts?slug=" + slug)
.then(function(response) {
if (!response.ok) {
throw Error(response.statusText);
}
return response.json();
})
.then(function(res) {
that.setState({ post: res[0] });
});
}

renderPosts() {
return (
<div className="card">
<div className="card-body">
<Helmet>
<title>{this.state.post.title.rendered}</title>
<meta name="description" content={this.state.post.excerpt.rendered.replace(/</?[^>]+(>|$)/g, "")} />
</Helmet>
<h1 className="card-title">{this.state.post.title.rendered}</h1>
<p className="card-text">
<small className="text-muted">
{this.state.post.author_name} &ndash;{" "}
{this.state.post.published_date}
</small>
</p>
{this.state.post.featured_image_src ? (
<img
className="featured-image"
src={this.state.post.featured_image_src}
alt="featured image"
/>
) : null}
<p
className="card-text"
dangerouslySetInnerHTML={{
__html: this.state.post.content.rendered
}}
/>
</div>
</div>
);
}

renderEmpty() {
return (
<div></div>
);
}

render() {
var href = window.location.href+"/?view=react";
return (
<div className="container post-entry">
{this.state.post.title ? this.renderPosts() : this.renderEmpty()}
</div>
);
}
}

export default Detail;


As I added ComponentDidUpdate(), it works but it renders loop back top first detail before render new post. I use like this.



componentDidUpdate() {

var that = this;
var url = window.location.href.split("/");
var slug = url.pop() || url.pop();
console.log(CelestialSettings.URL.api + "/posts?slug=" + slug);
fetch(CelestialSettings.URL.api + "/posts?slug=" + slug)
.then(function(response) {
if (!response.ok) {
throw Error(response.statusText);
}
return response.json();
})
.then(function(res) {
that.setState({ post: res[0] });
});
}


Any suggestion for my issue? Thank you so much.










share|improve this question

























  • is your <Detail> component exported with withRouter

    – Gabriele Petrioli
    Nov 19 '18 at 14:11











  • @GabrielePetrioli I do not know it. Can you explain me?

    – Hai Tien
    Nov 19 '18 at 14:11











  • Please show the code with your Detail component.

    – Gabriele Petrioli
    Nov 19 '18 at 14:17











  • @GabrielePetrioli Thank you so much. I updated detail component

    – Hai Tien
    Nov 19 '18 at 14:18











  • Added answer with a solution.

    – Gabriele Petrioli
    Nov 19 '18 at 14:23














1












1








1








I use Router like the code below to switch between components includes Home, Sidebar, Detail, Category.



For the first load, It will display all recent posts, featured posts.
When I click a post to go detail It work well.
In detail page, I click to render new post but It does not render.



My code:



class App extends React.Component {
render () {
// if ('serviceWorker' in navigator) {
// const registration = runtime.register();
// }
module.hot.accept();
$("body").removeClass();
$("body").addClass("homepage");
<Helmet>
<title>{blog_title}</title>
<meta name="description" content={blog_description} />
</Helmet>
const {feature, main, sidebar, mainbottom, header } = this.props;
return (
<div id="all">
{header}
<div className="container">
<div className="main-feature" id="main-feature">
{feature}
</div>
</div>
<div id="content" className="site-content">
<div className="container">
<div className="divcontainer">
<div id="po-homepage" className="content-area">
{main}
</div>
<aside id="secondary" className="sidebar widget-area">
<div className="popular_post" id="popular_post">
{sidebar}
</div>
</aside>
</div>
</div>
</div>
<div className="cat-list">
<div className="container">
<div className="thecategories" id="thecategories">
{mainbottom}
</div>
</div>
</div>
</div>
)
}
}


Please see photo:



enter image description here



My detail post:



import React, {Component} from "react"; //nếu chỉ import React thì sẽ cần React.Component
import $ from 'jquery';
import { Helmet } from "react-helmet";
import {
BrowserRouter as Router,
Route,
Switch
} from 'react-router-dom';

class Detail extends React.Component {
constructor(props) {
super(props);
this.state = {
post: {}
};
}

componentDidMount() {

//scroll to detail
$(document).ready(function(){
$("html, body").animate({ scrollTop: $("#content").offset().top - 100 }, 500);
$("body").removeClass();
$("body").addClass("detailpage");
});

console.log(this.props.detailink);

var that = this;
var url = window.location.href.split("/");
var slug = url.pop() || url.pop();
// console.log(CelestialSettings.URL.api + "/posts?slug=" + slug);
fetch(CelestialSettings.URL.api + "/posts?slug=" + slug)
.then(function(response) {
if (!response.ok) {
throw Error(response.statusText);
}
return response.json();
})
.then(function(res) {
that.setState({ post: res[0] });
});
}

renderPosts() {
return (
<div className="card">
<div className="card-body">
<Helmet>
<title>{this.state.post.title.rendered}</title>
<meta name="description" content={this.state.post.excerpt.rendered.replace(/</?[^>]+(>|$)/g, "")} />
</Helmet>
<h1 className="card-title">{this.state.post.title.rendered}</h1>
<p className="card-text">
<small className="text-muted">
{this.state.post.author_name} &ndash;{" "}
{this.state.post.published_date}
</small>
</p>
{this.state.post.featured_image_src ? (
<img
className="featured-image"
src={this.state.post.featured_image_src}
alt="featured image"
/>
) : null}
<p
className="card-text"
dangerouslySetInnerHTML={{
__html: this.state.post.content.rendered
}}
/>
</div>
</div>
);
}

renderEmpty() {
return (
<div></div>
);
}

render() {
var href = window.location.href+"/?view=react";
return (
<div className="container post-entry">
{this.state.post.title ? this.renderPosts() : this.renderEmpty()}
</div>
);
}
}

export default Detail;


As I added ComponentDidUpdate(), it works but it renders loop back top first detail before render new post. I use like this.



componentDidUpdate() {

var that = this;
var url = window.location.href.split("/");
var slug = url.pop() || url.pop();
console.log(CelestialSettings.URL.api + "/posts?slug=" + slug);
fetch(CelestialSettings.URL.api + "/posts?slug=" + slug)
.then(function(response) {
if (!response.ok) {
throw Error(response.statusText);
}
return response.json();
})
.then(function(res) {
that.setState({ post: res[0] });
});
}


Any suggestion for my issue? Thank you so much.










share|improve this question
















I use Router like the code below to switch between components includes Home, Sidebar, Detail, Category.



For the first load, It will display all recent posts, featured posts.
When I click a post to go detail It work well.
In detail page, I click to render new post but It does not render.



My code:



class App extends React.Component {
render () {
// if ('serviceWorker' in navigator) {
// const registration = runtime.register();
// }
module.hot.accept();
$("body").removeClass();
$("body").addClass("homepage");
<Helmet>
<title>{blog_title}</title>
<meta name="description" content={blog_description} />
</Helmet>
const {feature, main, sidebar, mainbottom, header } = this.props;
return (
<div id="all">
{header}
<div className="container">
<div className="main-feature" id="main-feature">
{feature}
</div>
</div>
<div id="content" className="site-content">
<div className="container">
<div className="divcontainer">
<div id="po-homepage" className="content-area">
{main}
</div>
<aside id="secondary" className="sidebar widget-area">
<div className="popular_post" id="popular_post">
{sidebar}
</div>
</aside>
</div>
</div>
</div>
<div className="cat-list">
<div className="container">
<div className="thecategories" id="thecategories">
{mainbottom}
</div>
</div>
</div>
</div>
)
}
}


Please see photo:



enter image description here



My detail post:



import React, {Component} from "react"; //nếu chỉ import React thì sẽ cần React.Component
import $ from 'jquery';
import { Helmet } from "react-helmet";
import {
BrowserRouter as Router,
Route,
Switch
} from 'react-router-dom';

class Detail extends React.Component {
constructor(props) {
super(props);
this.state = {
post: {}
};
}

componentDidMount() {

//scroll to detail
$(document).ready(function(){
$("html, body").animate({ scrollTop: $("#content").offset().top - 100 }, 500);
$("body").removeClass();
$("body").addClass("detailpage");
});

console.log(this.props.detailink);

var that = this;
var url = window.location.href.split("/");
var slug = url.pop() || url.pop();
// console.log(CelestialSettings.URL.api + "/posts?slug=" + slug);
fetch(CelestialSettings.URL.api + "/posts?slug=" + slug)
.then(function(response) {
if (!response.ok) {
throw Error(response.statusText);
}
return response.json();
})
.then(function(res) {
that.setState({ post: res[0] });
});
}

renderPosts() {
return (
<div className="card">
<div className="card-body">
<Helmet>
<title>{this.state.post.title.rendered}</title>
<meta name="description" content={this.state.post.excerpt.rendered.replace(/</?[^>]+(>|$)/g, "")} />
</Helmet>
<h1 className="card-title">{this.state.post.title.rendered}</h1>
<p className="card-text">
<small className="text-muted">
{this.state.post.author_name} &ndash;{" "}
{this.state.post.published_date}
</small>
</p>
{this.state.post.featured_image_src ? (
<img
className="featured-image"
src={this.state.post.featured_image_src}
alt="featured image"
/>
) : null}
<p
className="card-text"
dangerouslySetInnerHTML={{
__html: this.state.post.content.rendered
}}
/>
</div>
</div>
);
}

renderEmpty() {
return (
<div></div>
);
}

render() {
var href = window.location.href+"/?view=react";
return (
<div className="container post-entry">
{this.state.post.title ? this.renderPosts() : this.renderEmpty()}
</div>
);
}
}

export default Detail;


As I added ComponentDidUpdate(), it works but it renders loop back top first detail before render new post. I use like this.



componentDidUpdate() {

var that = this;
var url = window.location.href.split("/");
var slug = url.pop() || url.pop();
console.log(CelestialSettings.URL.api + "/posts?slug=" + slug);
fetch(CelestialSettings.URL.api + "/posts?slug=" + slug)
.then(function(response) {
if (!response.ok) {
throw Error(response.statusText);
}
return response.json();
})
.then(function(res) {
that.setState({ post: res[0] });
});
}


Any suggestion for my issue? Thank you so much.







reactjs






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 24 '18 at 4:33







Hai Tien

















asked Nov 19 '18 at 14:06









Hai TienHai Tien

80041530




80041530













  • is your <Detail> component exported with withRouter

    – Gabriele Petrioli
    Nov 19 '18 at 14:11











  • @GabrielePetrioli I do not know it. Can you explain me?

    – Hai Tien
    Nov 19 '18 at 14:11











  • Please show the code with your Detail component.

    – Gabriele Petrioli
    Nov 19 '18 at 14:17











  • @GabrielePetrioli Thank you so much. I updated detail component

    – Hai Tien
    Nov 19 '18 at 14:18











  • Added answer with a solution.

    – Gabriele Petrioli
    Nov 19 '18 at 14:23



















  • is your <Detail> component exported with withRouter

    – Gabriele Petrioli
    Nov 19 '18 at 14:11











  • @GabrielePetrioli I do not know it. Can you explain me?

    – Hai Tien
    Nov 19 '18 at 14:11











  • Please show the code with your Detail component.

    – Gabriele Petrioli
    Nov 19 '18 at 14:17











  • @GabrielePetrioli Thank you so much. I updated detail component

    – Hai Tien
    Nov 19 '18 at 14:18











  • Added answer with a solution.

    – Gabriele Petrioli
    Nov 19 '18 at 14:23

















is your <Detail> component exported with withRouter

– Gabriele Petrioli
Nov 19 '18 at 14:11





is your <Detail> component exported with withRouter

– Gabriele Petrioli
Nov 19 '18 at 14:11













@GabrielePetrioli I do not know it. Can you explain me?

– Hai Tien
Nov 19 '18 at 14:11





@GabrielePetrioli I do not know it. Can you explain me?

– Hai Tien
Nov 19 '18 at 14:11













Please show the code with your Detail component.

– Gabriele Petrioli
Nov 19 '18 at 14:17





Please show the code with your Detail component.

– Gabriele Petrioli
Nov 19 '18 at 14:17













@GabrielePetrioli Thank you so much. I updated detail component

– Hai Tien
Nov 19 '18 at 14:18





@GabrielePetrioli Thank you so much. I updated detail component

– Hai Tien
Nov 19 '18 at 14:18













Added answer with a solution.

– Gabriele Petrioli
Nov 19 '18 at 14:23





Added answer with a solution.

– Gabriele Petrioli
Nov 19 '18 at 14:23












1 Answer
1






active

oldest

votes


















2














Your Detail component needs to be aware that the url changed and since no relevant properties are passed when you try to render it you must use the withRouter HOC provided by react router



so at the top of your Details component file



import {
BrowserRouter as Router,
Route,
Switch,
withRouter // add this (and the comma in the above line)
} from 'react-router-dom';


and at the bottom where you export it use



export default withRouter(Detail);




Update



Reading your Details code a bit more i see that you fetch the content on the ComponentDidMount lifecycle event, but when you load a new post you remain to the same page so the Details component is not unmounted/remounted, it is just updated with new props and so the ComponentDidMount does not fire again. You will have to also use ComponentDidUpdate



Some additional info





  1. Since you are using the react-router you should not be parsing the window.location.href yourself trying to figure the slug. You can automatically pass it down from the props provided by the router.



    <!-- language: lang-js -->

    <Route
    path={CelestialSettings.path + 'posts/:slug'}
    render={(props) => <App header={<Header/>}
    main={<Detail slug={props.match.slug} detailink={CelestialSettings.path + 'posts/:slug'} />}
    sidebar={<Popular />}
    feature={<Featurex/>}
    mainbottom={<Categories/>} />} />



  2. Then in your ComponentDidUpdate



    <!-- language: lang-js -->

    componentDidUpdate(newProps) {
    const {slug} = newProps;
    const that = this; // you do not need this if you use arrow functions

    if (slug !== this.props.slug) {
    fetch(CelestialSettings.URL.api + "/posts?slug=" + slug)
    .then(function(response) {
    if (!response.ok) {
    throw Error(response.statusText);
    }
    return response.json();
    })
    .then(function(res) {
    that.setState({
    post: res[0]
    });
    });
    }
    }







share|improve this answer


























  • Thank you so much but it seems that it does not work. Do you know reason why?

    – Hai Tien
    Nov 19 '18 at 14:32






  • 2





    @HaiTien i see. Reading your Details code a bit more i see that you fetch the content on the ComponentDidMount, but when you change load a new post you remain to the same page so the Details component is not unmounted/remounted, it is just updated with new props so the ComponentDidMount does not fire again. You will have to also use ComponentDidUpdate.

    – Gabriele Petrioli
    Nov 19 '18 at 15:03








  • 1





    @GabrielePetrioli Wouldn't that be info that should be part of the answer instead of as a comment? :)

    – Icepickle
    Nov 19 '18 at 15:28






  • 1





    @HaiTien updated answer

    – Gabriele Petrioli
    Nov 19 '18 at 16:11






  • 1





    @Icepickle fair point. Added it to updated answer

    – Gabriele Petrioli
    Nov 19 '18 at 16:14











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53376384%2freact-router-not-rendered-with-second-click%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









2














Your Detail component needs to be aware that the url changed and since no relevant properties are passed when you try to render it you must use the withRouter HOC provided by react router



so at the top of your Details component file



import {
BrowserRouter as Router,
Route,
Switch,
withRouter // add this (and the comma in the above line)
} from 'react-router-dom';


and at the bottom where you export it use



export default withRouter(Detail);




Update



Reading your Details code a bit more i see that you fetch the content on the ComponentDidMount lifecycle event, but when you load a new post you remain to the same page so the Details component is not unmounted/remounted, it is just updated with new props and so the ComponentDidMount does not fire again. You will have to also use ComponentDidUpdate



Some additional info





  1. Since you are using the react-router you should not be parsing the window.location.href yourself trying to figure the slug. You can automatically pass it down from the props provided by the router.



    <!-- language: lang-js -->

    <Route
    path={CelestialSettings.path + 'posts/:slug'}
    render={(props) => <App header={<Header/>}
    main={<Detail slug={props.match.slug} detailink={CelestialSettings.path + 'posts/:slug'} />}
    sidebar={<Popular />}
    feature={<Featurex/>}
    mainbottom={<Categories/>} />} />



  2. Then in your ComponentDidUpdate



    <!-- language: lang-js -->

    componentDidUpdate(newProps) {
    const {slug} = newProps;
    const that = this; // you do not need this if you use arrow functions

    if (slug !== this.props.slug) {
    fetch(CelestialSettings.URL.api + "/posts?slug=" + slug)
    .then(function(response) {
    if (!response.ok) {
    throw Error(response.statusText);
    }
    return response.json();
    })
    .then(function(res) {
    that.setState({
    post: res[0]
    });
    });
    }
    }







share|improve this answer


























  • Thank you so much but it seems that it does not work. Do you know reason why?

    – Hai Tien
    Nov 19 '18 at 14:32






  • 2





    @HaiTien i see. Reading your Details code a bit more i see that you fetch the content on the ComponentDidMount, but when you change load a new post you remain to the same page so the Details component is not unmounted/remounted, it is just updated with new props so the ComponentDidMount does not fire again. You will have to also use ComponentDidUpdate.

    – Gabriele Petrioli
    Nov 19 '18 at 15:03








  • 1





    @GabrielePetrioli Wouldn't that be info that should be part of the answer instead of as a comment? :)

    – Icepickle
    Nov 19 '18 at 15:28






  • 1





    @HaiTien updated answer

    – Gabriele Petrioli
    Nov 19 '18 at 16:11






  • 1





    @Icepickle fair point. Added it to updated answer

    – Gabriele Petrioli
    Nov 19 '18 at 16:14
















2














Your Detail component needs to be aware that the url changed and since no relevant properties are passed when you try to render it you must use the withRouter HOC provided by react router



so at the top of your Details component file



import {
BrowserRouter as Router,
Route,
Switch,
withRouter // add this (and the comma in the above line)
} from 'react-router-dom';


and at the bottom where you export it use



export default withRouter(Detail);




Update



Reading your Details code a bit more i see that you fetch the content on the ComponentDidMount lifecycle event, but when you load a new post you remain to the same page so the Details component is not unmounted/remounted, it is just updated with new props and so the ComponentDidMount does not fire again. You will have to also use ComponentDidUpdate



Some additional info





  1. Since you are using the react-router you should not be parsing the window.location.href yourself trying to figure the slug. You can automatically pass it down from the props provided by the router.



    <!-- language: lang-js -->

    <Route
    path={CelestialSettings.path + 'posts/:slug'}
    render={(props) => <App header={<Header/>}
    main={<Detail slug={props.match.slug} detailink={CelestialSettings.path + 'posts/:slug'} />}
    sidebar={<Popular />}
    feature={<Featurex/>}
    mainbottom={<Categories/>} />} />



  2. Then in your ComponentDidUpdate



    <!-- language: lang-js -->

    componentDidUpdate(newProps) {
    const {slug} = newProps;
    const that = this; // you do not need this if you use arrow functions

    if (slug !== this.props.slug) {
    fetch(CelestialSettings.URL.api + "/posts?slug=" + slug)
    .then(function(response) {
    if (!response.ok) {
    throw Error(response.statusText);
    }
    return response.json();
    })
    .then(function(res) {
    that.setState({
    post: res[0]
    });
    });
    }
    }







share|improve this answer


























  • Thank you so much but it seems that it does not work. Do you know reason why?

    – Hai Tien
    Nov 19 '18 at 14:32






  • 2





    @HaiTien i see. Reading your Details code a bit more i see that you fetch the content on the ComponentDidMount, but when you change load a new post you remain to the same page so the Details component is not unmounted/remounted, it is just updated with new props so the ComponentDidMount does not fire again. You will have to also use ComponentDidUpdate.

    – Gabriele Petrioli
    Nov 19 '18 at 15:03








  • 1





    @GabrielePetrioli Wouldn't that be info that should be part of the answer instead of as a comment? :)

    – Icepickle
    Nov 19 '18 at 15:28






  • 1





    @HaiTien updated answer

    – Gabriele Petrioli
    Nov 19 '18 at 16:11






  • 1





    @Icepickle fair point. Added it to updated answer

    – Gabriele Petrioli
    Nov 19 '18 at 16:14














2












2








2







Your Detail component needs to be aware that the url changed and since no relevant properties are passed when you try to render it you must use the withRouter HOC provided by react router



so at the top of your Details component file



import {
BrowserRouter as Router,
Route,
Switch,
withRouter // add this (and the comma in the above line)
} from 'react-router-dom';


and at the bottom where you export it use



export default withRouter(Detail);




Update



Reading your Details code a bit more i see that you fetch the content on the ComponentDidMount lifecycle event, but when you load a new post you remain to the same page so the Details component is not unmounted/remounted, it is just updated with new props and so the ComponentDidMount does not fire again. You will have to also use ComponentDidUpdate



Some additional info





  1. Since you are using the react-router you should not be parsing the window.location.href yourself trying to figure the slug. You can automatically pass it down from the props provided by the router.



    <!-- language: lang-js -->

    <Route
    path={CelestialSettings.path + 'posts/:slug'}
    render={(props) => <App header={<Header/>}
    main={<Detail slug={props.match.slug} detailink={CelestialSettings.path + 'posts/:slug'} />}
    sidebar={<Popular />}
    feature={<Featurex/>}
    mainbottom={<Categories/>} />} />



  2. Then in your ComponentDidUpdate



    <!-- language: lang-js -->

    componentDidUpdate(newProps) {
    const {slug} = newProps;
    const that = this; // you do not need this if you use arrow functions

    if (slug !== this.props.slug) {
    fetch(CelestialSettings.URL.api + "/posts?slug=" + slug)
    .then(function(response) {
    if (!response.ok) {
    throw Error(response.statusText);
    }
    return response.json();
    })
    .then(function(res) {
    that.setState({
    post: res[0]
    });
    });
    }
    }







share|improve this answer















Your Detail component needs to be aware that the url changed and since no relevant properties are passed when you try to render it you must use the withRouter HOC provided by react router



so at the top of your Details component file



import {
BrowserRouter as Router,
Route,
Switch,
withRouter // add this (and the comma in the above line)
} from 'react-router-dom';


and at the bottom where you export it use



export default withRouter(Detail);




Update



Reading your Details code a bit more i see that you fetch the content on the ComponentDidMount lifecycle event, but when you load a new post you remain to the same page so the Details component is not unmounted/remounted, it is just updated with new props and so the ComponentDidMount does not fire again. You will have to also use ComponentDidUpdate



Some additional info





  1. Since you are using the react-router you should not be parsing the window.location.href yourself trying to figure the slug. You can automatically pass it down from the props provided by the router.



    <!-- language: lang-js -->

    <Route
    path={CelestialSettings.path + 'posts/:slug'}
    render={(props) => <App header={<Header/>}
    main={<Detail slug={props.match.slug} detailink={CelestialSettings.path + 'posts/:slug'} />}
    sidebar={<Popular />}
    feature={<Featurex/>}
    mainbottom={<Categories/>} />} />



  2. Then in your ComponentDidUpdate



    <!-- language: lang-js -->

    componentDidUpdate(newProps) {
    const {slug} = newProps;
    const that = this; // you do not need this if you use arrow functions

    if (slug !== this.props.slug) {
    fetch(CelestialSettings.URL.api + "/posts?slug=" + slug)
    .then(function(response) {
    if (!response.ok) {
    throw Error(response.statusText);
    }
    return response.json();
    })
    .then(function(res) {
    that.setState({
    post: res[0]
    });
    });
    }
    }








share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 19 '18 at 17:35

























answered Nov 19 '18 at 14:23









Gabriele PetrioliGabriele Petrioli

149k23197253




149k23197253













  • Thank you so much but it seems that it does not work. Do you know reason why?

    – Hai Tien
    Nov 19 '18 at 14:32






  • 2





    @HaiTien i see. Reading your Details code a bit more i see that you fetch the content on the ComponentDidMount, but when you change load a new post you remain to the same page so the Details component is not unmounted/remounted, it is just updated with new props so the ComponentDidMount does not fire again. You will have to also use ComponentDidUpdate.

    – Gabriele Petrioli
    Nov 19 '18 at 15:03








  • 1





    @GabrielePetrioli Wouldn't that be info that should be part of the answer instead of as a comment? :)

    – Icepickle
    Nov 19 '18 at 15:28






  • 1





    @HaiTien updated answer

    – Gabriele Petrioli
    Nov 19 '18 at 16:11






  • 1





    @Icepickle fair point. Added it to updated answer

    – Gabriele Petrioli
    Nov 19 '18 at 16:14



















  • Thank you so much but it seems that it does not work. Do you know reason why?

    – Hai Tien
    Nov 19 '18 at 14:32






  • 2





    @HaiTien i see. Reading your Details code a bit more i see that you fetch the content on the ComponentDidMount, but when you change load a new post you remain to the same page so the Details component is not unmounted/remounted, it is just updated with new props so the ComponentDidMount does not fire again. You will have to also use ComponentDidUpdate.

    – Gabriele Petrioli
    Nov 19 '18 at 15:03








  • 1





    @GabrielePetrioli Wouldn't that be info that should be part of the answer instead of as a comment? :)

    – Icepickle
    Nov 19 '18 at 15:28






  • 1





    @HaiTien updated answer

    – Gabriele Petrioli
    Nov 19 '18 at 16:11






  • 1





    @Icepickle fair point. Added it to updated answer

    – Gabriele Petrioli
    Nov 19 '18 at 16:14

















Thank you so much but it seems that it does not work. Do you know reason why?

– Hai Tien
Nov 19 '18 at 14:32





Thank you so much but it seems that it does not work. Do you know reason why?

– Hai Tien
Nov 19 '18 at 14:32




2




2





@HaiTien i see. Reading your Details code a bit more i see that you fetch the content on the ComponentDidMount, but when you change load a new post you remain to the same page so the Details component is not unmounted/remounted, it is just updated with new props so the ComponentDidMount does not fire again. You will have to also use ComponentDidUpdate.

– Gabriele Petrioli
Nov 19 '18 at 15:03







@HaiTien i see. Reading your Details code a bit more i see that you fetch the content on the ComponentDidMount, but when you change load a new post you remain to the same page so the Details component is not unmounted/remounted, it is just updated with new props so the ComponentDidMount does not fire again. You will have to also use ComponentDidUpdate.

– Gabriele Petrioli
Nov 19 '18 at 15:03






1




1





@GabrielePetrioli Wouldn't that be info that should be part of the answer instead of as a comment? :)

– Icepickle
Nov 19 '18 at 15:28





@GabrielePetrioli Wouldn't that be info that should be part of the answer instead of as a comment? :)

– Icepickle
Nov 19 '18 at 15:28




1




1





@HaiTien updated answer

– Gabriele Petrioli
Nov 19 '18 at 16:11





@HaiTien updated answer

– Gabriele Petrioli
Nov 19 '18 at 16:11




1




1





@Icepickle fair point. Added it to updated answer

– Gabriele Petrioli
Nov 19 '18 at 16:14





@Icepickle fair point. Added it to updated answer

– Gabriele Petrioli
Nov 19 '18 at 16:14


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53376384%2freact-router-not-rendered-with-second-click%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks

Calculate evaluation metrics using cross_val_predict sklearn

Insert data from modal to MySQL (multiple modal on website)