Skip to content

Instantly share code, notes, and snippets.

@ryanflorence
Last active January 30, 2016 06:59
Show Gist options
  • Save ryanflorence/bbe292d4f5994500bd3b to your computer and use it in GitHub Desktop.
Save ryanflorence/bbe292d4f5994500bd3b to your computer and use it in GitHub Desktop.
import React from 'react'
// need a getter and a hash of requestId:results or something
// to use in server rendering
let results = []
function updateTitle() {
document.title = results[results.length - 1]
}
const Title = React.createClass({
getInitialState() {
return {
index: results.push('') - 1
}
},
componentWillUnmount() {
results.pop()
},
componentDidMount: updateTitle,
componentDidUpdate: updateTitle,
render() {
const { render } = this.props
results[this.state.index] = typeof render === 'function'
? render(results[this.state.index - 1] || '')
: render
return this.props.children || null
}
})
export default Title
@ryanflorence
Copy link
Author

Usage

This assumes you don't unmount a title in the middle:

like:

<Title render="first">
// lower component
<Title render={first => `${first} | second`}/>
// lower component
<Title render={second => `${second} | third`}/>

// then unmount the second title at some point, it'll all explode, seems like a strange use-case,
// and not sure there's a way around it, no real way to know the order these things are rendered
// when one in the middle goes away

BUT ANYWAY I'm really happy with this

import React from 'react';
import Title from './Title'

const App = React.createClass({
  render() {
    return (
      <div>
        <Title render="Github Notifications"/>
        <Stuff/>
        <Notification/> {/* this.props.children in React Router */}
      </div>
    )
  }
})

const Notification = React.createClass({
  getInitialState() {
    return {
      issue: {
        title: 'Loading ...'
      }
    }
  },

  componentDidMount() {
    this.fetchIssue((err, issue) => {
      this.setState({ issue })
    })
  },

  render() {
    return (
      <Title render={prev => `${prev} | ${this.state.issue.title}`}>
        <Stuff/>
      </Title>
    )
  }
})

export { App }

@ryanflorence
Copy link
Author

can use <Title/> anywhere, but nice to see it up top of render so you know it's messing w/ the title.

@jehoshua02
Copy link

Seems strange to me that you would pass children into <Title>. What is the reasoning for that?

@ryanflorence
Copy link
Author

oops, this wont' get updates when parents change

@ryanflorence
Copy link
Author

@jehoshua02 I agree, feels stranger to just have a title floating around somewhere in render though, you can do it either way.

@RoyalIcing
Copy link

Seems a bit gross to changing document.title within the component. What if you had a updateTitle function in context? That way, App can decide what to do with it. Or even a nested component, such as a panel/modal/card, can have its own title hierarchy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment