I’ve been told that it’s a best practice to use classes only for containers and to use functions for components. So containers have state and components are dumb functions that only recieve and send props to and from the containers.
The problem I’m finding with this is that it leads to really bloated containers. Not only that but if a container includes many different components then the methods in these containers are a mixture of many different unrelated functionalities.
This goes against the idea of keeping everything very modular. For example if I have a “submit comment” component in my container I would expect the submitCommentHandler method to also be in the relevant component not mixed together in the Post container with a ton of other handlers for unrelated functionalities like being next to the ratePostHandler and the userLoginHandler.
I’m new to react so maybe I’m missing something but how to reconcile this “best practice” with all the other issues it presents?
There are a couple of misconceptions in your post, possibly stemming from misconceptions in whatever best practices article you are reading.
When the core idea of containers + components started surfacing many examples were not doing it correctly.
// DO NOT DO THIS
let FormComponent = ({ data, handleSubmit }) =>
<form onSubmit={handleSubmit}>
{...something with data...}
</form>
class FormContainer extends React.Component {
state = { data: [] }
submitForm = formData => {
api.post(formData).then(data => this.setState({ data }))
}
render() {
return (
<div>
<FormComponent
data={this.state.data}
handleSubmit={this.submitForm}
/>
</div>
)
}
}
This is a pretty classic container + component example, however it's 100% useless and goes against the entire idea. In order for containers to be modular they need to be completely agnostic about render logic. If you hardcode the presentation in the container, then it's all just one big component split into two sections, somewhat arbitrarily I might add.
You can read about higher order components, but I'm going to focus on standard that's gaining traction: render props.
class FormContainer extends React.Component {
state = { data: [] }
submitForm = formData => {
api.post(formData).then(data => this.setState({ data }))
}
render() {
return this.props.children({
data: this.state.data,
submitForm: this.submitForm
})
}
}
Now you have a container that does one thing, that can be used repeatedly anywhere in your app, with any presentational component like so:
let SomewhereInYourApp = () => (
<FormContainer>
{({ data, submitForm }) => (
<div>
{/* put whatever you want here.. it's modular! */}
<FormComponent data={data} handleSubmit={submitForm} />
</div>
)}
</FormContainer>
)
Then you can make as many containers as you need which only do the specific business logic that's important to it and nest them however it makes sense to do so. I don't think any best practices say to combine everything into a single container. Nesting containers is perfectly acceptable.
If you have many containers and the nesting gets a little too pyramidy, consider using HoCs or a utility like react-adopt to compose containers that use render props.
Screenshot of composed containers from react-adopt:
Related
I'm working on a React component library that allows for client-side data filtering by passing an array of objects and an <input/> as props to a <SearchFilter/> component. I want to return the filtered results to a separate <SearchResults/> component that can be rendered elsewhere in the tree (i.e. the results component doesn't have to be a child of the input component).
I've got the filtering figured out, but I'm not sure the best route to take in React on getting the filtered data to the <SearchResults/> component.
This is what I'd like to end up with...
<SearchFilter
data={data}
input={<input type="text" value={value} onChange={this.handleChange}/>}
/>
Then, using Render Props to return the data and map over that to return JSX, there would be the results component. Something like this...
<SearchResults
render={data => (
data.map(el => (
<div>
<span>{data.someProperty}</span>
</div>
)
)}
/>
This is what I'd like to achieve because I want to allow for rendering the <SearchFilter/> component at one place in the tree, and allow the <SearchResults/> component to be rendered elsewhere, so that there's maximum flexibility in how the tree is composed and, therefore, how the view is rendered.
I've looked into the Context API, but it seems like that would require a handful more components to be a part of my library, which further complicates what I'm trying to achieve. If that's the only way around it, then that's fine, but I wanted to ask and see if anyone can think of another solution.
Thanks!
The bigger issue is that you will need to manage a state that is shared between components on a higher level, i.e., any component that will wrap these other two components, ultimately. With plain React, this state would be managed by the parent (or ancestor) component, passing down the relevant values as props. This opposed to the, usually bad, idea to have sibling components influence each other's state, since you well get into the "who's boss here"-problem.
The thing the Context API handles is not having to pass down props for things that typically don't change (or: typically shouldn't cause renders to trigger often).
A global state store, such as Redux, can help you modelling this, but in essence it's not much more than 'a' component managing state, and other components rendering according to that state. Events within the lower components trigger changes in the data, which will cause the state to change, which will cause the props of the children to change, which then will cause re-renders.
I'd advise you to try using this simple pattern:
class Search ... {
state = {data: [], text: ""}
render() {
return (
<div>
<SearchFilter
data={this.state.data}
onSearch={() => this.fetchNewData()}
onChange={(e) => this.setState({text: e.targetElement.value})}
text={this.state.text}
/>
<SearchResults data={this.state.data} />
</div>
);
}
fetchNewData() {
fetch('/url?text=' + this.state.text)
.then((newData) => { this.setState({data: newData}); })
}
}
Something along these lines. If you have trouble modelling stuff like this, you can use Redux to force you to do it in a similar way, and avoid managing local state intermixing with global state (which is typically something that is hard to manage).
If you do this right, components that have no state (i.e., aren't responsible for managing state and thus have no event handlers) can all become pure components, i.e. stateless components, i.e. functions that return JSX based on props:
const SearchResults = ({data}) => <div>{data.map( () => <etc /> )}</div>
You could create a data store class that holds your filter, pass it in as a property to both components, and have your SearchFilter component change a value in that.
I have a Modal component which is a popup window. I need to set different components to the bodyContainer.
<Modal
show={this.props.first.showModal}
size={this.props.first.sizeModal}
bodyContainer={this.props.first.modalBodyContainer}
/* bodyContainer={<Mail {...this.props}/>} */
onClose={this.props.firstActions.onCloseModalHome}
/>
As I understand the redux philosophy I can do it like this
// Search Patient actions
export const onSearchPatient = (ur, token) => dispatch => (
callToApiWithToken(`patient/by/ur/${ur}`, token)
.then(response =>
((response.data === null) ? dispatch(onSearchPatientNotFound(ur)) : dispatch(onSearchPatientFound(response.data))),
)
.catch(error => ({ type: psActions.ON_SUBMIT_ERROR }))
);
export const onSearchPatientFound = createAction(psActions.ON_SEARCH_PATIENT_FOUND);// data
export const onSearchPatientNotFound = createAction(psActions.ON_SEARCH_PATIENT_NOT_FOUND);
//Reducer
case psActions.ON_SEARCH_PATIENT_FOUND:
return {
...state,
showModal: true,
modalBodyContainer: <PatientDetails {...action.payload} />,
};
case psActions.ON_SEARCH_PATIENT_NOT_FOUND:
return {
...state,
error: true,
errorMsg: <div>The Patient <strong>{action.payload}</strong> is not in the system</div>,
};
But my colleague arguing that this is a bad practice. Specifically I'm talking about
modalBodyContainer: <PatientDetails {...action.payload} />
It is possible to relocate render logic to the Modal but in this case I need to create a switch for all possible components.
What is the right way to do this?
Edited
I have two ideas how to do this. What is the best to use?
//Action
export const setModalBody = createAction(psActions.SET_MODAL_BODY);//component
//Reducer
case psActions.SET_MODAL_BODY:
return {
...state,
showModal: true,
modalBodyContainer: action.payload />,
};
//Usage
onClick={() => searchPatient.length > 0 && onSearch(searchPatient, token).then(patientFound && setModalBody(<Patient {...props} />)
OR
const Modal = ({...}) => (
{{
//Something like this
//switch based on prop.bodyComponentType
//in this case I need to import all possible components to the Modal
sectionA: (
<SectionAComponent />
),
sectionB: (
<SectionBComponent />
),
sectionC: (
<SectionCComponent />
)
}[section]}
)
Edited 2
It is not about redux actions, it's about a component rendering inside hoc related to actions.
Your coworker is right.
The philosophy of Redux/React is largely around separation of concerns and making things loosely coupled but highly cohesive. For this situation, that means that your action should not know anything about the component it will cause to render (loosely coupled), but will be a complete definition of the result of your api call (highly cohesive).
I would have both of your reducer functions modify the same attribute of the redux state. Afterall, they represent the same piece of data, just with different values. One represents a success, and the other a failure. So I would have them both modify patientFoundStatus and provide it a value (perhaps using http codes, or a success/failure constant defined elsewhere). Then use this value to determine the output of your modal.
So why is this better?
Well for a couple of reasons. The most important is to consider how your code would need to be modified if, later on, this action needed to produce a different (additional) result in the view. Let's say that it is now used to pre-populate a form with the patient's information. How would your code need to change?
Given the code you have above, it would need to be entirely rewritten or duplicated. The modal body components would be completely irrelevant to this new feature, and the "success/failure" information (and patient information) needed would need to be added.
But consider if these actions only returned the data relevant to the view. Well now, what you do with that data is up to you. The reducers and actions could remain entirely unchanged, and you could merely use that pre-existing slice of state to impact a new section of your app.
That's one of the biggest advantages to react/redux when used correctly. Over time, what you end up creating is a flexible toolbox that makes adding new features trivial, because all the plumbing is well in place and wholly distinct from how it is utilized. Low coupling. High cohesion.
I can't seem to grasp the understanding of why higher order components are highly valued over the regular components? I read a tutorial on them and that higher order components are good because they: 1) Allow code re-use, logic and bootstrap abstraction. 2) Able to do render highjacking. 3) Able to abstract state and manipulate them. 4) Able to manipulate props. Source: link
An example of a higher order component in code was shown there as:
function refsHOC(WrappedComponent) {
return class RefsHOC extends React.Component {
proc(wrappedComponentInstance) {
wrappedComponentInstance.method()
}
render() {
const props = Object.assign({}, this.props, {ref: this.proc.bind(this)})
return <WrappedComponent {...props}/>
}
}
}
These look almost the same exact code as a regular class definition that receives props and you are still able to "manipulate props" and "manipulate state" inside that class
class Something extends React.Component {
constructor(props) {
super(props);
this.state = { food: 'no_food_received_yet' }
}
componentDidMount() {
this.setState({ food: 'apple' });
}
render() {
return (
<div>
<p>{ this.state.food }</p>
<h2>{ this.props.food }</h2>
</div>
);
}
}
Actually I didn't get to manipulate or mutate the props but I can just receive them, apply them to state and output that state.
This is not to bash on higher order components---this is actually the complete opposite. I need to understand where I am wrong and why I should integrate higher order components into my react app.
HOCs are absolutely useful, but they're useful in the same way any "higher order" function is.
Consider the following component:
let Button = props => <button style={{ color: props.color }} />
You could make another component called BlueButton:
let BlueButton = props => <Button color="blue" />
There's nothing wrong with that, but maybe you want any component to be able to be blue, not just a button. Instead we can make a generic HOC that "blueifies" the passed component:
let blueify = Component => props => <Component {...props} style={{ color: 'blue' }} />
Then you can make blue buttons, blue divs, blue anything!
let BlueButton = blueify(Button)
let BlueDiv = blueify(props => <div {...props} />)
Imagine you had an app where certain screens were private and only available to authenticated users. Imagine you had 3 such screens. Now on each screen's container component you can have the logic to check if the user is authenticated and let them through if they are, or send them back to login when they are not. This means having the exact same logic happen 3 times. With a HOC you can code that logic just once and then wrap each private screen in with the HOC thus giving you the same logic over and over, but the code only needs to exist in one place. This is an example of great code reuse that HOCs offer.
Higher order components are more generalized, and so in theory can be applied to a broader number of cases. In the more general sense, higher-order components (and higher-level languages) tend to be more expressive.
In your case, the difference is readily apparent. The non-generalized (lower-order) component has hard-coded HTML in it. This is programming 101; constant declarations like PI are preferred over hard-coded declarations like 3.14159 because they give meaning to magic numbers and allow one point of modification.
A simple example of a higher order "component" (in this case a higher order function) is a sort function that takes as one of its arguments an ordering function. By allowing the ordering to be controlled by an outboard function, you can modify the behavior of the sort without modifying the sort function itself.
I work mainly with Handlebars JS now, but I am looking at JSX. Is there a JSX equivalent to Handlebars partials? I want to know if I can create small bits of markup that I can reuse in several different JSX views.
It doesn't provide partials. Some things about React:
React doesn't provide any notion of partials. The fundamental, atomic unit of React is the component.
Instead of passing a partial, you'd create a component or components and re-use those. Even better than a partial because it's a function, so it's encapsulated and testable!
If the markup is small, it should probably either be moved up into a parent component or down into a simpler one
Generally, my rule of thumb is that components should follow the principle of single responsibility or separation of concerns. If something doesn't seem to fit into a component, you've likely got problems in the other two components and could reconsider them, too :)
Another couple rules of thumb to go by when thinking about components:
code smells should usually end up as components (repeating something over and over again, etc.)
components are usually either presentational or containerized. The latter have roles in the props/state tree for an app (you never "see them")
refactor things into components as you need to; don't start out encapsulating everything, because you may have prematurely refactored and created more problems for yourself
the most reusable and decoupled components are like the best functions or objects: clean, flexible, testable, and they do address a single concern
at the same time, don't go crazy and turn everything into a component. i.e. you don't (usually) want:
<Letter>R</Letter><Letter>e</Letter><Letter>a</Letter><Letter>c</Letter><Letter>t</Letter>
Here's an incredibly simple example:
'use strict';
const OuterComponent = React.createClass({
render() {
return (
<div>Outer{this.props.children}</div>
);
}
});
const ReusableComponent = React.createClass({
render() {
return (
<div>Am I reusable? {this.props.reusable && 'Yeah!' }</div>
);
}
});
ReactDOM.render(
<OuterComponent>
<ReusableComponent reusable={true}/>
</OuterComponent>,
document.getElementById('container')
);
Will render:
OuterComponent
Am I reusable? Yeah!
Note, though, that using creatClass provides you more than you might need if you're not working with mutable state (which is provided to you within the component via this.state), you can easily use what are sometimes called "stateless functional components" (because they are, well, stateless and returned by functions). These could easily be arrow functions implicitly returning the JSX (which is essentially just React.createElement() generator)
const OuterComponent = (props) => <div>Outer{this.props.children}</div>;
const ReusableComponent = (props) => <div>Am I reusable? {this.props.reusable && 'Yeah!' }</div>;
ReactDOM.render(
<OuterComponent>
<ReusableComponent reusable={true}/>
</OuterComponent>,
document.getElementById('container')
);
Just create a component for that. Components can be as simple or as complex as you want them to be.
Example:
function Badge(props) {
return <span className="badge">{props.counter}</span>
}
With a corresponding .badge CSS class, this could be a very simply component that renders as a red circle with a number, and is used as <Badge counter={42} />.
I'm trying to understand stateless components and what the difference is between these examples:
class App {
render() {
return (
<div>
{this.renderAFunction('hello')}
</div>
);
}
renderAFunction(text) {
return (
<p>{text}</p>
);
}
}
and this:
class App {
render() {
return(
<div>
<RenderAFunction text='hello'/>
</div>
);
}
}
const RenderAFunction = ({text}) => (
<p>{text}</p>
);
Or if there is any difference at all?
Functionally, there is absolutely no difference. Both end up rendering a paragraph element, but there are other aspects to consider. There are three points to make (in my opinion) when examining both methods:
Reusability: You have to understand to separate components when you need to. If renderAFunction is just meant to generate some JSX based on, for example, an API request, then it's fine being in a method. But if you want to reuse it somewhere else, then separate it into it's own component. A huge part of React is component reusability and getting rid of code duplication. Separating the method into it's own component would be imperative to accomplish this.
Purpose: There are reason to use stateless function components and reasons not to. The whole point of stateless functional components is to not have state and be presentational. If you need to do something that involves the React lifecycle or internal state, keep it as a method, or new class depending on if you want it reusable.
Performance: Using a stateless functional component would be less efficient. This is because it's a component, not just some JSX returned from a method. As of right now, the React team plans on making some optimizations for stateless functional components because they do not contain state and are merely presentational, but this probably won't happen until after React Fiber is done and thus your stateless functional component has no optimizations versus a regular full-fledged class component. That makes it incredibly inefficient versus a method returning some JSX, especially if it's just used once in another component.
A good rule of thumb is to ask yourself, do I need it anywhere else? If not, then keep it in a method. If you don't need it anywhere else, separating the JSX into a separate component would have worse performance and wouldn't follow React's core principles.
If you are going to need it somewhere else, then separate the component so you follow React's concept of reusability.
Your App's render function will be translated into following JS code for your first example:
render() {
return React.createElement(
'div',
null,
this.renderAFunction('hello')
);
}
And the following one for the second one:
render() {
return React.createElement(
'div',
null,
React.createElement(RenderAFunction, { text: 'hello' })
);
}
While they both looks almost the same, there is one significant difference: laziness. React will execute RenderAFunction body only in case it gonna be mounted to the DOM hierarchy.
It is insignificant is your case, but imaging following example:
const LazyApp = () => {
const heavy = <div><HeavyStuff /></div>
// ...
return <div>done it</div>
}
const HardWorkingApp = () => {
const heavy = <div>{HeavyStuff()}</div>
// ...
return <div>done it</div>
}
const HeavyStuff = () => {
// ... do heavy rendering here
}
Lazy app will not perform any heavy stuff at all. Maybe it is not very clear from that synthetic example why one would do anything like that at all. But there are real-world examples out there, when something conceptually similar (creating Components without rendering them) is happening.
Basically, both will serve the same purpose. But the real advantage of creating a component is its reusability.
If you have to render that particular piece of jsx just for this component. Then, there is no need to create a separate component.