React: useImperativeHandle should warn when second arg isn't a function

Created on 18 Jan 2019  路  11Comments  路  Source: facebook/react

I've noticed a strange bug with the react redux forwardRef opt-in.
If i use it with a connected class component, everything is ok:

const MyComponent = class Test extends React.Component {
  foo = () => console.log("Print foo from Test component");
  render() {
    return null;
  }
};

const ConnectedComponent = connect(
  null,
  null,
  null,
  { forwardRef: true }
)(MyComponent);

const store = createStore(() => {});

function App() {
  return (
    <Provider store={store}>
      <ConnectedComponent
        ref={ref => {
          if (ref) ref.foo();
        }}
      />
    </Provider>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

If i use it with a connected functional component that use forwardRef with useImperativeHandle, i obtain a strange error: create is not a function in commitHookEffectList react-dom method.

const MyComponent = React.forwardRef((props, ref) => {
  useImperativeHandle(ref, {
    foo: () => console.log("Print foo from Test component")
  });

  return null;
});

const ConnectedComponent = connect(
  null,
  null,
  null,
  { forwardRef: true }
)(MyComponent);

const store = createStore(() => {});

function App() {
  return (
    <Provider store={store}>
      <ConnectedComponent
        ref={ref => {
          if (ref) ref.foo();
        }}
      />
    </Provider>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

I create a codepen to reproduce the issue: https://codesandbox.io/s/r7rpml460o

PS: Sorry for the cors error, but i don't find the way to add react@nextas cdn

starter Enhancement good first issue (taken)

All 11 comments

I believe the issue here is that useImperativeHandle expects the second argument to be a function that returns the reference:

// before (your sample code)
useImperativeHandle(ref, {
  foo: () => console.log("Print foo from Test component")
});
// after
useImperativeHandle(ref, () => ({
  foo: () => console.log("Print foo from Test component")
}));

See: https://reactjs.org/docs/hooks-reference.html#useimperativehandle for more information about the API of the hook.

Maybe the error thrown could be more clear?

You're right, useImperativeHandle accept a function as second argument.
A warning on wrong argument type could be a good idea.

Ill take this issue on

Sure

i get TypeError: React.useImperativeMethods is not a function in 16.8.0-alpha.1 but when back to 16.7.0-alpha.2 not get this error

@AhmedElywa The hook was renamed in this PR: https://github.com/facebook/react/pull/14565

Most likely between the 16.7 alpha and 16.8 alpha

Yeah, it was renamed.

yes it work good after rename it where i can get changes between alpha version ?

Commit log. We don't write changelogs for alphas.

@Aberman12 I'm taking this in https://github.com/facebook/react/pull/14647 since we want to get Hooks out sooner.

alright np

Was this page helpful?
0 / 5 - 0 ratings