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

\$\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
\$\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

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.