Skip to content

Instantly share code, notes, and snippets.

@duyenho
Created March 5, 2018 08:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save duyenho/8dc3a9c5b2cd3b4ea0234c63b6de647a to your computer and use it in GitHub Desktop.
Save duyenho/8dc3a9c5b2cd3b4ea0234c63b6de647a to your computer and use it in GitHub Desktop.
performance - how to avoid bindings in react's render function
// I have three forms. On each form, it is possible to add and remove form blocks. I created these util functions:
export function appendFormBlock(type) {
// New block ids created from the type, eg. 'dependant_1', 'authPerson_2', etc..
const newBlock = `${type}_${this.state[`${type}FormBlocks`].length}`;
this.setState({
[`${type}FormBlocks`]: this.state[`${type}FormBlocks`].concat([newBlock]),
});
}
export function removeFormBlock(id) {
const type = id.split('_')[0];
this.setState({
[`${type}FormBlocks`]: this.state[`${type}FormBlocks`].filter(block => block !== id),
});
}
export default class DoctorsPage extends React.Component {
constructor(props) {
super(props)
this.state = { doctorFormBlocks: ['doctor_0'] }
}
render() {
return (
<div className="form__section">
{doctorFormBlocks.map((block, i) => (
<DoctorFormBlock
form={form}
key={block}
blockId={block}
index={i + 1}
handleRemove={removeFormBlock.bind(this, block)}
/>
))}
<AddRemoveButton
typeToAdd="doctor"
handleAppend={appendFormBlock.bind(this, 'doctor')}
/>
</div>
)
}
}
// I learned that binding functions in the render function is bad for performance - this is the main issue.
// Here is the form block:
export default class DoctorFormBlock extends React.Component {
static propTypes = {
form: PropTypes.object.isRequired,
index: PropTypes.number.isRequired,
blockId: PropTypes.string.isRequired,
handleRemove: PropTypes.func.isRequired,
};
render() {
const {form, index, blockId, handleRemove} = this.props;
return (
<section className="form__block" id={blockId}>
// Shows the remove button from the second instance of the form block onwards
{index > 1 && <AddRemoveButton isRemove handleRemove={handleRemove} />}
<h3>Doctor {index}</h3>
<LayoutField form={form} fieldId="doctorsSpeciality" sectionId="doctorDetailsForm" />
<LayoutField form={form} fieldId="name" sectionId="doctorDetailsForm" />
<LayoutField form={form} fieldId="address" sectionId="doctorDetailsForm" />
<LayoutField form={form} fieldId="contactNumber" sectionId="doctorDetailsForm" />
</section>
);
}
}
// And the add/remove button
export default class AddRemoveButton extends React.Component {
static propTypes = {
isRemove: PropTypes.bool,
typeToAdd: PropTypes.string,
handleAppend: PropTypes.func,
handleRemove: PropTypes.func,
};
static defaultProps = {
isRemove: false,
typeToAdd: '',
handleAppend: () => {},
handleRemove: () => {},
};
render() {
const {typeToAdd, isRemove, handleAppend, handleRemove} = this.props;
return (
<div className="btn-holder">
{typeToAdd && (
<Button
key="btnAdd"
variant={Button.Variant.LINK}
className="add-btn"
onClick={handleAppend}
>
Add {typeToAdd}
</Button>
)}
{isRemove && (
<Button
key="btnRemove"
variant={Button.Variant.LINK}
className="remove-btn"
onClick={handleRemove}
>
Remove
</Button>
)}
</div>
);
}
}
// I tried a few different approaches but it all felt over-complicated
// https://medium.freecodecamp.org/why-arrow-functions-and-bind-in-reacts-render-are-problematic-f1c08b060e36
// https://medium.freecodecamp.org/react-pattern-extract-child-components-to-avoid-binding-e3ad8310725e
// 1. How would you go about avoiding these bindings?
// 2. Do you think the utils are overkill and I should write them long hand on each pages for better readability?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment