Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React. When import function in component function, can i know why it didn`t work hooks setState..?

I've tried to code splitting for call function when it`s needed.

so i divided function from component.

//Split.js
const Split = () => {
  return <div>It`s text</div>;
};

export default Split;

It`s work in React Class Component.

//App.js
class App extends Component {
  state = {
    Split: null
  };
  handleClick = () => {
    import("./Split").then(({ default: Split }) => {
      this.setState({
        Split
      });
    });
  };
  render() {
    const { Split } = this.state;
    return (
      <div>
        <button onClick={this.handleClick}>Click Me</button>
        {Split && <Split />}
      </div>
    );
  }
}

here's class component link(working) https://codesandbox.io/s/code-splitting-1-bbtpe

But when i changed to Hooks Function Component, It didn`t work..

const App = () => {
  const [split, setSplit] = useState(null);
  const handleClick = () => {
    import("./Split").then(({ default: Split }) => {
      // console.log(SplitMe());
      setSplit(Split);
    });
  };

  const SplitMe = split;
  return (
    <div>
      <button onClick={handleClick}>Click Me</button>
      {SplitMe && <SplitMe />}
    </div>
  );
};

and evoked error

Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.

here's function component link(working) https://codesandbox.io/s/code-splitting-2-4flbm

Can i know what's different class component's setState with function component's setState(hook)?

thank you!


2 Answers

setState and the function returned by useState takes two types of arguments:

  1. You can set a value directly to it.
  2. You can pass it a function which they would call with the previous state as argument.

In the function version, you have imported a function Split and used it in:

setSplit(Split);

Notice that Split here is a function and what would apply is the second version of setState. It would call the function directly instead of keeping the function as a component. If the component is called with (), the type of <Split /> is invalid (because React can no longer call it, it's not a function)

To get around this, you can store Split as an object as you did in the case of the class component.

const [split, setSplit] = useState(null);
const handleClick = () => {
  import("./Split").then(({ default: Split }) => {
    setSplit({ Split });
  });
};
const Split = split ? split.Split : null;

Now setSplit sees a object as an argument and sets it directly.

Codesandbox

like image 145
Agney Avatar answered Jun 22 '26 12:06

Agney


State can only store Strings or Objects, and there is no differences between class and hook so this come from the way you implemented your hook.

On component based, you are doing :

state = {
    Split: null
};

this.setState({ Split })

Using hooks, you need to store your imported function in an object which is what was done by default in the class based component.

To make it work, simply store it this way:

import React, { useState } from "react";

const App = () => {
  const [splits, setSplits] = useState({});
  const handleClick = () => {
    import("./Split").then(({ default: SplitMe }) => {
      // console.log(SplitMe);
      setSplits({ SplitMe });
    });
  };

  const { SplitMe } = splits;
  return (
    <div>
      <button onClick={handleClick}>Click Me</button>
      {SplitMe && <SplitMe />}
    </div>
  );
};

export default App;

like image 45
sebastienbarbier Avatar answered Jun 22 '26 14:06

sebastienbarbier



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!