no-set-state.js 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /**
  2. * @fileoverview Prevent usage of setState
  3. * @author Mark Dalgleish
  4. */
  5. 'use strict';
  6. const values = require('object.values');
  7. const Components = require('../util/Components');
  8. const docsUrl = require('../util/docsUrl');
  9. const report = require('../util/report');
  10. // ------------------------------------------------------------------------------
  11. // Rule Definition
  12. // ------------------------------------------------------------------------------
  13. const messages = {
  14. noSetState: 'Do not use setState',
  15. };
  16. /** @type {import('eslint').Rule.RuleModule} */
  17. module.exports = {
  18. meta: {
  19. docs: {
  20. description: 'Disallow usage of setState',
  21. category: 'Stylistic Issues',
  22. recommended: false,
  23. url: docsUrl('no-set-state'),
  24. },
  25. messages,
  26. schema: [],
  27. },
  28. create: Components.detect((context, components, utils) => {
  29. /**
  30. * Checks if the component is valid
  31. * @param {Object} component The component to process
  32. * @returns {boolean} True if the component is valid, false if not.
  33. */
  34. function isValid(component) {
  35. return !!component && !component.useSetState;
  36. }
  37. /**
  38. * Reports usages of setState for a given component
  39. * @param {Object} component The component to process
  40. */
  41. function reportSetStateUsages(component) {
  42. for (let i = 0, j = component.setStateUsages.length; i < j; i++) {
  43. const setStateUsage = component.setStateUsages[i];
  44. report(context, messages.noSetState, 'noSetState', {
  45. node: setStateUsage,
  46. });
  47. }
  48. }
  49. return {
  50. CallExpression(node) {
  51. const callee = node.callee;
  52. if (
  53. callee.type !== 'MemberExpression'
  54. || callee.object.type !== 'ThisExpression'
  55. || callee.property.name !== 'setState'
  56. ) {
  57. return;
  58. }
  59. const component = components.get(utils.getParentComponent(node));
  60. const setStateUsages = (component && component.setStateUsages) || [];
  61. setStateUsages.push(callee);
  62. components.set(node, {
  63. useSetState: true,
  64. setStateUsages,
  65. });
  66. },
  67. 'Program:exit'() {
  68. values(components.list())
  69. .filter((component) => !isValid(component))
  70. .forEach((component) => {
  71. reportSetStateUsages(component);
  72. });
  73. },
  74. };
  75. }),
  76. };