2

I'm currently updating my application to React 16.8 so I can use the awesome new hook feature. Updating the React package (and all the dependencies) was not a problem and everything works fine. But when I try to setup ESLint it keeps giving me te following error when I'm trying to use hooks:

React Hook "useEffect" is called in function "projectInfo" which is neither a React function component or a custom React Hook function

My component looks like this:

import React, { useState} from 'react';

const myComponent = () => {
  const [counter, setCounter] = useState(0);

  return <span onClick={() => setCounter(counter + 1)}>{counter}</span>;
};

export default myComponent;

My .eslintsrc file looks like this:

{
    "extends": ["react-app"],
    "plugins": [
        "react-hooks"
      ],
    "rules": {
        "no-console": ["warn", { "allow": ["info", "error"] }],
        "quotes": ["warn", "single"],
        "semi": ["warn", "always"],
        "no-debugger": ["warn"],
        "eqeqeq": ["warn"],
        "no-else-return": ["warn"],
        "no-extra-bind": ["warn"],
        "jsx-a11y/href-no-hash": false,
        "prefer-destructuring": [
            "warn",
            {
                "array": true,
                "object": true
            },
            {
                "enforceForRenamedProperties": false
            }
        ],
        "react-hooks/rules-of-hooks": "warn"
    }
}

EDIT: In the error it says that there is an error in projectInfo. For simplicity reasons I changed that with the myComponent code above. The projectinfo looked like this:

const projectInfo = props => {
  const [createdLink, setCreatedLink] = useState(null);
  const [getProjectStatus, asyncGetProject] = useAsyncCall(props.getProject);
  const [generateLinkStatus, asyncGenerateLink] = useAsyncCall(api.questionnaire.generateQuestionnaireToken);

  // ComponentWillMount
  useEffect(() => {
    if (!props.project) {
      asyncGetProject(props.match.params.id);
    }
  }, []);

  const generateQuestionnaireLink = async () => {
    const response = await asyncGenerateLink(props.project.questionnaireId);
    const createdLink = `${window.location.host}/questionnaire/${response.data.id}`;
    setCreatedLink(createdLink);
  };

  const { translate, project, updateProject } = props;
  const errorMessage = generateLinkStatus.error.message || getProjectStatus.error.message;
  return (
    <div className={styles.profileContainer}>
      <Message message={errorMessage} status={'error'} />
      <BackButton />
      <Loading isVisible={getProjectStatus.loading} />
      {project && (
        <Fragment>
          <EditableForm entity={project} onSubmit={updateProject}>
            <Label text={translate('projectName')} name={'name'} />
            <Checkbox text={translate('isPublic')} name={'isPublic'} />
          </EditableForm>
          <Loading isVisible={generateLinkStatus.loading} />
          <Button text={translate('generateButton')} clickHandler={generateQuestionnaireLink} />
          <br />
          {createdLink && <span>{createdLink}</span>}
        </Fragment>
      )}
    </div>
  );
};

const mapStateToProps = state => {
  return {
    translate: getTranslate(state.locale),
    project: state.project.currentProject
  };
};

const mapDispatchToProps = dispatch => {
  return {
    getProject: id => dispatch(actions.getProject(id)),
    updateProject: (id, params) => dispatch(actions.updateProject(id, params))
  };
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(projectInfo);
2
  • what is "projectInfo" ? can you show the code of "projectInfo" ? Commented Feb 9, 2019 at 11:27
  • I added the projectInfo component in the question. See the Edit section Commented Feb 9, 2019 at 11:36

1 Answer 1

10

The problem here is your component name starting with a lowercase letter.

See eslint-plugin-react-hooks code source

/**
 * Checks if the node is a React component name. React component names must
 * always start with a non-lowercase letter. So `MyComponent` or `_MyComponent`
 * are valid component names for instance.
 */

function isComponentName(node) {
  if (node.type === 'Identifier') {
    return !/^[a-z]/.test(node.name);
  } else {
    return false;
  }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

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.