Skip to content

Instantly share code, notes, and snippets.

@xnimorz
Last active September 1, 2018 22:28
Show Gist options
  • Save xnimorz/d4044f1c84274a494adfc6d36a916170 to your computer and use it in GitHub Desktop.
Save xnimorz/d4044f1c84274a494adfc6d36a916170 to your computer and use it in GitHub Desktop.
WhyObjectRefsAreGood.jsx
// With callbacs:
class List extends Component {
constructor(props) {
super(props);
props.items.map(item =>
this.refsCallbacks[item.id] = (el) => this.refs.items[item.id] = el;
);
// also you can store refCallbacks in state.
}
componentWillReceiveProps(nextProps) {
if (nextProps.items !== this.props.items) {
nextProps.items.map(item => {
if (this.refsCallbacks[item.id]) {
return;
}
this.refsCallbacks[item.id] = (el) => this.refs.items[item.id] = el;
});
}
}
componentDidMount() {
this.calculate();
}
componentDidUpdate() {
this.calculate();
}
refsCallbacks = {};
refs = {items: {}};
calculate() {
// Calculate width of elements and hide elements that overflow container
this.refs.items.map(...); // Good
}
render() {
const { items } = this.props;
return (
<div className='container'>
{items.map(item =>
<div
ref={this.refCallbacks[item.id]}
key={item.id}
className='item'
>
{item.content}
</div>
)}
</div>
);
}
}
// With callbacs:
class List extends Component {
receiveRef = (el) => {
this.refs.items[el.dataset.id] = el;
}
componentDidMount() {
this.calculate();
}
componentDidUpdate() {
this.calculate();
}
refsCallbacks = {};
refs = {items: {}};
calculate() {
// Calculate width of elements and hide elements that overflow container
this.refs.items.map(...); // Good
}
render() {
const { items } = this.props;
return (
<div className='container'>
{items.map(item =>
<div
ref={this.receiveRef}
data-id={item.id}
key={item.id}
className='item'
>
{item.content}
</div>
)}
</div>
);
}
}
// With inline callbacks
class List extends Component {
componentDidMount() {
this.calculate();
}
componentDidUpdate() {
this.calculate();
}
refs = {items: {}};
calculate() {
// Calculate width of elements and hide elements that overflow container
this.refs.items.map(...); // Good
}
render() {
const { items } = this.props;
return (
<div className='container'>
{items.map(item =>
<div
ref={(el) => this.refs.items[item.id] = el} // There is some specific work after each render https://reactjs.org/docs/refs-and-the-dom.html#caveats
// ref={(el) => this.refs.items.push(el)} // bad idea: https://reactjs.org/docs/refs-and-the-dom.html#caveats
key={item.id}
className='item'
>
{item.content}
</div>
)}
</div>
);
}
}
// With inline callbacks
class List extends Component {
constructor() {
super(props);
// less code than in previous example
props.items.map(item => {
this.refs.items[item.id] = React.createRef();
});
}
componentWillReceiveProps(nextProps) {
if (nextProps.items !== this.props.items) {
props.items.map(item => {
if (this.refs.items[item.id]) {
return;
}
this.refs.items[item.id] = React.createRef();
});
}
}
componentDidMount() {
this.calculate();
}
componentDidUpdate() {
this.calculate();
}
refs = {items: {}};
calculate() {
// Calculate width of elements and hide elements that overflow container
this.refs.items.map(...); // Good
}
render() {
const { items } = this.props;
return (
<div className='container'>
{items.map(item =>
<div
ref={this.refs.items[item.id]}
key={item.id}
className='item'
>
{item.content}
</div>
)}
</div>
);
}
}
// With String refs:
class List extends Component {
componentDidMount() {
this.calculate();
}
componentDidUpdate() {
this.calculate();
}
calculate() {
// Calculate width of elements and hide elements that overflow container
Object.keys(this.refs).map(...) // Bad practise
}
render() {
const { items } = this.props;
return (
<div className='container'>
{items.map(item => <div ref={`item-${item.id}`} key={item.id} className='item'>{item.content}</div>)}
</div>
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment