How can I change the title on each page for universal app. So for example I would like About.jsx to have About | React Go title, Dashboard.jsx to have Dashboard | React Go and so on.. I would also like to make use of titleTemplate
You can use react-helmet. This is already included in this package. Just read its documentation.
Yes, but adding <Helmet title='About' /> to About.jsx will change all of the title to About
There is an another option defaultTitle.
<Helmet title='About' defaultTitle=' | React Go'/>
Doesn't really do anything. Problem here is that if you add <Helmet ... /> code to any of the containers and when you go to that page the whole title will be replaced. So when I go to /about with <Helmet title="About /> the title will change to About but going back to dashboard the title will still be About
You should also put Helmet in Dashboard such like <Helmet title='Dashboard' />
Did that didn't work. Have you tried it yourself?
Im running my own blog based on this package and everything goes fine.
I'll tell you from basic.
First you have to add
<Helmet defaultTitle=" | React Go" />
in app/containers/App.jsx
Second you add Helmet each in About.jsx and Dashboard.jsx.
<Helmet title="About" />
<Helmet title="Dashboard" />
These inherit App.jsx's Helmet, so defaultTitle options will work.
Yeah tried that one already but it overrides the Meta.jsx headers.
Meta.jsx is not related with client side title. So if you want to use Helmet in client-side, you should make Meta.jsx totally different from current Meta.jsx
For example meta.jsx in my blog looks like below.
export default (routes, state, params) => {
let title;
const post = state.posting.post;
if (routes && routes[1]) {
switch (routes[1].path) {
case '/category/:category/post/:id':
if (post) {
const filteredContent = filterTag(post.content).substring(0, 150);
title = `${post.category} ${post.title}`;
replaceMeta(config.meta, [
{ name: 'description', content: filteredContent },
{ property: 'og:title', content: title },
{ property: 'og:description', content: filteredContent },
{ property: 'og:type', content: 'article' },
{ property: 'og:url', content: `${url}/category/${post.category}/post/${post._id}` },
{ name: 'twitter:title', content: title },
{ name: 'twitter:description', content: filteredContent },
]);
}
break;
case '/category/:category':
title = params.category;
replaceMeta(config.meta, [
{ property: 'og:title', content: title },
{ property: 'og:url', content: `${url}/category/${title}` },
{ property: 'og:type', content: 'website' },
{ name: 'twitter:title', content: title },
{ name: 'description', content: `${title} κ΄λ ¨ κΈ λ¦¬μ€νΈμ
λλ€` },
{ property: 'og:description', content: `${title} κ΄λ ¨ κΈ λ¦¬μ€νΈμ
λλ€` },
{ name: 'twitter:description', content: `${title} κ΄λ ¨ κΈ λ¦¬μ€νΈμ
λλ€` },
]);
break;
case '/settings':
title = 'μ€μ ';
replaceMeta(config.meta, [
{ property: 'og:title', content: title },
{ property: 'og:url', content: `${url}/settings` },
{ property: 'og:type', content: 'website' },
{ name: 'twitter:title', content: title },
{ name: 'description', content: 'μ€μ νμ΄μ§μ
λλ€.' },
{ property: 'og:description', content: 'μ€μ νμ΄μ§μ
λλ€.' },
{ name: 'twitter:description', content: 'μ€μ νμ΄μ§μ
λλ€.' },
]);
break;
case '/login':
title = 'λ‘κ·ΈμΈ';
replaceMeta(config.meta, [
{ property: 'og:title', content: title },
{ property: 'og:url', content: `${url}/login` },
{ property: 'og:type', content: 'website' },
{ name: 'twitter:title', content: title },
{ name: 'description', content: 'λ‘κ·ΈμΈ νμ΄μ§μ
λλ€.' },
{ property: 'og:description', content: 'λ‘κ·ΈμΈ νμ΄μ§μ
λλ€.' },
{ name: 'twitter:description', content: 'λ‘κ·ΈμΈ νμ΄μ§μ
λλ€.' },
]);
break;
case '/join':
title = 'νμκ°μ
';
replaceMeta(config.meta, [
{ property: 'og:title', content: title },
{ property: 'og:url', content: `${url}/join` },
{ property: 'og:type', content: 'website' },
{ name: 'twitter:title', content: title },
{ name: 'description', content: 'νμκ°μ
νμ΄μ§μ
λλ€.' },
{ property: 'og:description', content: 'νμκ°μ
νμ΄μ§μ
λλ€.' },
{ name: 'twitter:description', content: 'νμκ°μ
νμ΄μ§μ
λλ€.' },
]);
break;
case '/tag/:name':
title = `${params.name} νκ·Έ κ²μ κ²°κ³Ό`;
replaceMeta(config.meta, [
{ property: 'og:title', content: title },
{ property: 'og:url', content: `${url}/tag/${params.name}` },
{ property: 'og:type', content: 'website' },
{ name: 'twitter:title', content: title },
{ name: 'description', content: `${params.name} νκ·Έ κ²μ κ²°κ³Ό νμ΄μ§μ
λλ€.` },
{ property: 'og:description', content: `${params.name} νκ·Έ κ²μ κ²°κ³Ό νμ΄μ§μ
λλ€.` },
{ name: 'twitter:description', content: `${params.name} νκ·Έ κ²μ κ²°κ³Ό νμ΄μ§μ
λλ€.` },
]);
break;
case '/portfolio':
title = 'ν¬νΈν΄λ¦¬μ€';
break;
default:
replaceMeta(config.meta, [
{ name: 'description', content: description },
{ property: 'og:url', content: url },
{ property: 'og:type', content: 'website' },
{ property: 'og:description', content: description },
{ property: 'og:title', content: config.defaultTitle },
{ name: 'twitter:title', content: config.defaultTitle },
{ name: 'twitter:description', content: description },
]);
break;
}
}
const Meta = () => (
<Helmet
htmlAttributes={config.htmlAttributes}
defaultTitle={title ? '' : config.defaultTitle}
titleTemplate={config.titleTemplate}
title={title || 'Main'}
meta={config.meta}
link={config.link}
/>
);
renderToString(<Meta />);
return Helmet.rewind();
};
and I use it in app/server.jsx like below
preRenderMiddleware(store.dispatch, props.components, props.params)
.then(() => {
const initialState = store.getState();
const componentHTML = (
<Provider store={store} key="provider">
<RouterContext {...props} />
</Provider>
);
const header = makeHeader(props.routes, initialState, props.params); // this is the part which import Meta.jsx
const finalHTML = `<!DOCTYPE html>${renderToString(
<Layout header={header} content={componentHTML} initialState={initialState} />
)}`;
res.status(200).send(finalHTML);
})
.catch((renderError) => {
console.error('renderError', renderError);
res.status(500).json(renderError);
});
Ah! I thought it was somehow connected with the client. I'm still new to this universal app thing. Thanks for the clarification. You've been a great help!
@mateeyow @ZeroCho Thanks for the great discussion! (And also for the quick response to giving a good solution!)
Given that there is a bit of confusion surrounding this, I think that it's a good indication that we should perhaps consider refactoring the behaviour of our <helmet>.
Perhaps:
<Helmet title={props.title} /> and the Composed Component. Something like below:
const meta = ComposedComponent => class extends React.Component {
render() {
return (
<div>
<Helmet title={props.title} meta={props.meta} link={props.link} />
<ComposedComponent {...props} />
</div>);
}
}
meta(About);
I will propose a solution here and see what you guys think!
@choonkending Yes. This is somewhat confusing because Meta.jsx is in the client directory. Other bolierplate projects use shared directory for shared components. Any thoughts about this?
@ZeroCho Apart from server.jsx and client.jsx I think all components should be shared on client and server - or at least that's where we should aim. I like having shared components, but my concern with having shared as a folder might make it even more confusing when creating components, particularly when we have to decide whether to put it in 1 of 3 folders. (Correct me if my understanding is wrong).
On a separate note, here's an initial spike - I've seen this used and I think it's a good starting point. This is to only handle client side, will hopefully remove Meta.jsx once I get this approach right.
@choonkending Looks good to me. Just I have one question. Is it good practice to wrap Container by Component? The Page component wraps Vote Container now.
Ah, also for SEO, I think we still need react-helmet for server side
I agree with @choonkending I don't think a shared folder is a good idea, but maybe a more detailed read me about meta information is in order.
@ZeroCho Looking at the code in your solution, I'm having a hard time replicating what you did. I'm not so sure where replaceMeta() and filterTags() are defined in your meta.jsx file. Also unsure about makeHeader() in server.js. I am looking to accomplish exactly what you have done for your SEO for my site and would love any direction or help you might have to suggest!
Thanks.
As an overall comment, @choonkending @caranicas; I saw you were trying for a page speed score enhancement. I think that would be a good move, but I would also suggest that we do get an enhancement for improving the seo of this project. I am proposing something where we can specify route-based title and meta tags as I think was proposed above. I'd be happy to contribute to a solution if I end up figuring this out. Are PRs currently addressing this that I have missed?
@brtw oh, replaceMeta and filterTags are not defined in my meta.jsx. It's in the separate file. replaceMeta is to change meta tag for each route and filterTags are for making meta description, which filters tags from the posts. makeHeader function uses both replaceMeta and filterTags function to make meta, link, script tags. You can easily make your own version of functions. If you need my exact code please tell me.
Totally agree with seo improvement. I have a branch for meta tags coming up
soon but won't have time to have it merged till next week :(
On Thu, 6 Oct 2016 12:35 Hyunyoung Cho [email protected] wrote:
@brtw https://github.com/brtw oh, replaceMeta and filterTags are not
defined in my meta.jsx. It's in the separate file. replaceMeta is to change
meta tag for each route and filterTags are for making meta description,
which filters tags from the posts. makeHeader function uses both
replaceMeta and filterTags function to make meta, link, script tagsβ
You are receiving this because you were mentioned.Reply to this email directly, view it on GitHub
https://github.com/reactGo/reactGo/issues/457#issuecomment-251845911,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ADnMbcpWO_X4GL2fZBflFxpWeUxuM7ovks5qxFBZgaJpZM4JqnqA
.
@ZeroCho Thanks! , @choonkending Great! I have plenty to be doing in my project till next week. I can wait for your merge and focus my efforts on some other features in my project. Does your branch support per-route or per-pathname titles and meta-properties?
Yes it will, you will have to specify it. Look at the comparision here, still some stuff to clean up for production - but it works on dev.
Need to find a bunker somewhere and finish this off next week (after Tuesday).
@choonkending Did you ever merge this? I tested it out and I was getting FOUC on page switches
@choonkending I'm considering implementing the proposed code to get a jump on improving the SEO of my project. Did you plan on changing anything before merging or is this good to go?
Hey there are still some changes needed for it:
I'll list more down later. Sorry for the delay mate, just been bogged down
recently. I'll whip something out soon
On Wed, 2 Nov 2016 23:49 brtw [email protected] wrote:
@choonkending https://github.com/choonkending I'm considering
implementing the proposed code
https://github.com/reactGo/reactGo/compare/get-betta-with-meta to get a
jump on improving the SEO of my project. Did you plan on changing anything
before merging or is this good to go?β
You are receiving this because you were mentioned.Reply to this email directly, view it on GitHub
https://github.com/reactGo/reactGo/issues/457#issuecomment-257854766,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ADnMbRtXY5LdMOCJs5160rqzSEdLx3Avks5q6IbBgaJpZM4JqnqA
.
Hey guys, a quick update, I've got this branch almost ready to go:
It became a pretty significant refactor, and only managed to get to it this week!
I'll create the PR once I fix the remaining issues and hopefully we can get some SEO juice!
https://github.com/reactGo/reactGo/pull/675
Will merge tomorrow at noon sharp. Haha. Sorry I took so long (and for the huge refactor) - I will endeavour to ship smaller code changes.
Merged! Closing now!
Please re-open if there's still an issue!
Most helpful comment
Yes it will, you will have to specify it. Look at the comparision here, still some stuff to clean up for production - but it works on dev.
Need to find a bunker somewhere and finish this off next week (after Tuesday).