user192344
user192344

Reputation: 1396

React HOC with WrappedComponent in Hook version Always re init the state

I have a HOC, currently i wanna revamp it to Hook version, however i found that it always render

let see the example:

const f = ()=> { console.log("init"); return "";}
const hoc = ({someProp = ""}) => WrappedComponent => {
   const HOC = ({...props}) => {
       const [selected, setSelected] = useState(f());
       return <WrappedComponent {...props} setSelected={setSelected}/>
   }
   return HOC;
}

f() will always call when setSelected trigger from WrappedComponent

let see the other example:

const f = ()=> { console.log("init"); return "";}
const hoc = ({someProp = ""}) => WrappedComponent => {
   class HOC extends Component {
         constructor(props) {
            super(props);
            this.state = {selected: f()}
            this.setSelected = this.setSelected.bind(this);
         }
         setSelected(value) {
            this.setState({selected:value})
        }
        render() {
           return <WrappedComponent {...props} setSelected={this.setSelected}/>

        }
  }

  return HOC;
}

f() will only call once

How do i solve this case if i must use Hoc Format, but just wanna hoc itself become a functional component?

or i just change

const [selected, setSelected] = useState(f()); 

to

const [selected, setSelected] = useState(() => f());

Upvotes: 1

Views: 162

Answers (2)

user192344
user192344

Reputation: 1396

the answer is change

const [selected, setSelected] = useState(f());

to

const [selected, setSelected] = useState(() => f());

and f() will only call once no matter how many time it render, except unmount

Upvotes: 0

edvard chen
edvard chen

Reputation: 2784

You are misusing the useState.

Every time the HOC render, f() will be called.

Let me verbose here, maybe the following code would make you see more clearly

const hoc = ({someProp = ""}) => WrappedComponent => {
   const HOC = ({...props}) => {
       const state = f(); // Sure, this line would be executed every time.
       const [selected, setSelected] = useState(state);
       ...
   }
  ...
}

I guess that you want to execute f() to get init state when initializing Component and then let the Component handle the state itself, although it is not recommended.

For this scenario, I would prefer one of the following approaches:

  1. Pass the result of f() from parent to HOC component

    This is the simplest way that create HOC and generate init state at same time

  2. use useEffect if the first time rendering with blank state is fine.

    You can think useEffect as old didMount lifecycle API.

Upvotes: 1

Related Questions