0
\$\begingroup\$

I have a common List in mind which looks something like this:

enter image description here

it has one remove button

one input in which user can enter the name of element and on clicking insert the element will be added in the list.

For this i have added HOC like this:

function ListHOC(Component, data, listName, placeholder) {
 return class extends React.Component {
 constructor() {
 super();
 this.state = { data, element: "" };
 }
 add = item => {
 const { data } = this.state;
 data.push(item);
 this.setState({ data });
 };
 remove = keyToRemove => {
 const { data } = this.state;
 const newData = data.filter(({ key }) => keyToRemove !== key);
 this.setState({ data: newData });
 };
 render() {
 const { data, element } = this.state;
 const updatedList = data.map(({ name, key }) => (
 <div style={{ display: "flex" }} key={key}>
 <div>{name}</div>
 <button onClick={() => this.remove(key)}>remove</button>
 </div>
 ));
 return (
 <>
 <div>{listName}: </div>
 <Component data={updatedList} {...this.props} />
 <input
 placeholder={placeholder}
 onChange={e => this.setState({ element: e.target.value })}
 />
 <button
 onClick={() => this.add({ name: element, key: data.length + 1 })}
 >
 insert
 </button>
 </>
 );
 }
 };
}

one thing i am not sure about is weather to use the input and button and listname inside HOC or not

link to codepen: https://codepen.io/saxenanihal95/pen/NWKVJOx?editors=1010

asked Feb 23, 2020 at 5:04
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

There's no reason to use a HOC for this, it can be done more simply and clearly with a component:

class List extends React.Component {
 state = { data: this.props.initialData, element: "" };
 add = item => {
 this.setState(prev => ({ data: prev.data.concat(item) }));
 };
 remove = keyToRemove => {
 this.setState(prev => ({
 data: prev.data.filter(({ key }) => keyToRemove !== key)
 }));
 };
 render() {
 const { data, element } = this.state;
 const { placeholder, listName } = this.props;
 return (
 <>
 <div>{listName}: </div>
 {data.map(({ name, key }) => (
 <div style={{ display: "flex" }} key={key}>
 <div>{name}</div>
 <button onClick={() => this.remove(key)}>remove</button>
 </div>
 ))}
 <input
 placeholder={placeholder}
 onChange={e => this.setState({ element: e.target.value })}
 />
 <button
 onClick={() => this.add({ name: element, key: data.length + 1 })}
 >
 insert
 </button>
 </>
 );
 }
}
const Users = () => (
 <List
 initialData={[
 { name: "a", key: 1 },
 { name: "b", key: 2 }
 ]}
 listName="Users"
 placeholder="insert user"
 />
);
const Comments = () => (
 <List initialData={[]} listName="Comments" placeholder="insert comment" />
);
const AnotherList = () => <Users />;
function App() {
 return (
 <div>
 <Users />
 <Comments />
 <AnotherList />
 </div>
 );
}
ReactDOM.render(<App />, document.getElementById("app"));

HOCs are generally better for cross-cutting concerns, or behavior (not presentation) which you want to add to any component. for example logging:

const withLogging = Component => props => {
 console.log('Props:', props);
 return <Component {...props} />;
}
const List = ({ name, data }) => ...
const ListWithLogging = withLogging(List); // <-- This will log all props
answered Feb 24, 2020 at 3:27
\$\endgroup\$
2
  • \$\begingroup\$ I have came across this blog: css-tricks.com/what-are-higher-order-components-in-react which is using search as common component so i got confused as you said we use HOC for behaviour(not presentation) please help to understand this \$\endgroup\$ Commented Apr 12, 2020 at 15:30
  • 1
    \$\begingroup\$ CSS-Tricks has some valuable resources, but I wouldn't consider the examples in that article the best use of HOCs. Take a look at the official React docs on HOCs (linked at the bottom of that article): reactjs.org/docs/higher-order-components.html - notice that none of those examples include any JSX in the HOC's render method other than the WrappedComponent. The HOCs in those examples are only used for behavioral/data concerns, not presentation. That said, you COULD use HOCs for presentation, but there are other patterns that would do it more clearly (like render props or hooks) \$\endgroup\$ Commented Apr 12, 2020 at 18:03

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.