no-access-state-in-setstate.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /**
  2. * @fileoverview Prevent usage of this.state within setState
  3. * @author Rolf Erik Lekang, Jørgen Aaberg
  4. */
  5. 'use strict';
  6. // ------------------------------------------------------------------------------
  7. // Requirements
  8. // ------------------------------------------------------------------------------
  9. const rule = require('../../../lib/rules/no-access-state-in-setstate');
  10. const RuleTester = require('eslint').RuleTester;
  11. const parserOptions = {
  12. ecmaVersion: 2018,
  13. ecmaFeatures: {
  14. jsx: true
  15. }
  16. };
  17. // ------------------------------------------------------------------------------
  18. // Tests
  19. // ------------------------------------------------------------------------------
  20. const ruleTester = new RuleTester();
  21. ruleTester.run('no-access-state-in-setstate', rule, {
  22. valid: [{
  23. code: [
  24. 'var Hello = React.createClass({',
  25. ' onClick: function() {',
  26. ' this.setState(state => ({value: state.value + 1}))',
  27. ' }',
  28. '});'
  29. ].join('\n'),
  30. parserOptions: parserOptions
  31. }, {
  32. code: [
  33. 'var Hello = React.createClass({',
  34. ' multiplyValue: function(obj) {',
  35. ' return obj.value*2',
  36. ' },',
  37. ' onClick: function() {',
  38. ' var value = this.state.value',
  39. ' this.multiplyValue({ value: value })',
  40. ' }',
  41. '});'
  42. ].join('\n'),
  43. parserOptions: parserOptions
  44. }, {
  45. // issue 1559: don't crash
  46. code: `
  47. var SearchForm = createReactClass({
  48. render: function () {
  49. return (
  50. <div>
  51. {(function () {
  52. if (this.state.prompt) {
  53. return <div>{this.state.prompt}</div>
  54. }
  55. }).call(this)}
  56. </div>
  57. );
  58. }
  59. });
  60. `,
  61. parserOptions: parserOptions
  62. }, {
  63. // issue 1604: allow this.state in callback
  64. code: `
  65. var Hello = React.createClass({
  66. onClick: function() {
  67. this.setState({}, () => console.log(this.state));
  68. }
  69. });
  70. `,
  71. parserOptions: parserOptions
  72. }, {
  73. code: `
  74. var Hello = React.createClass({
  75. onClick: function() {
  76. this.setState({}, () => 1 + 1);
  77. }
  78. });
  79. `,
  80. parserOptions: parserOptions
  81. }, {
  82. code: [
  83. 'var Hello = React.createClass({',
  84. ' onClick: function() {',
  85. ' var nextValueNotUsed = this.state.value + 1',
  86. ' var nextValue = 2',
  87. ' this.setState({value: nextValue})',
  88. ' }',
  89. '});'
  90. ].join('\n'),
  91. parserOptions: parserOptions
  92. }, {
  93. // https://github.com/yannickcr/eslint-plugin-react/pull/1611
  94. code: `
  95. function testFunction({a, b}) {
  96. };
  97. `,
  98. parserOptions: parserOptions
  99. }],
  100. invalid: [{
  101. code: [
  102. 'var Hello = React.createClass({',
  103. ' onClick: function() {',
  104. ' this.setState({value: this.state.value + 1})',
  105. ' }',
  106. '});'
  107. ].join('\n'),
  108. parserOptions: parserOptions,
  109. errors: [{
  110. message: 'Use callback in setState when referencing the previous state.'
  111. }]
  112. }, {
  113. code: [
  114. 'var Hello = React.createClass({',
  115. ' onClick: function() {',
  116. ' this.setState(() => ({value: this.state.value + 1}))',
  117. ' }',
  118. '});'
  119. ].join('\n'),
  120. parserOptions: parserOptions,
  121. errors: [{
  122. message: 'Use callback in setState when referencing the previous state.'
  123. }]
  124. }, {
  125. code: [
  126. 'var Hello = React.createClass({',
  127. ' onClick: function() {',
  128. ' var nextValue = this.state.value + 1',
  129. ' this.setState({value: nextValue})',
  130. ' }',
  131. '});'
  132. ].join('\n'),
  133. parserOptions: parserOptions,
  134. errors: [{
  135. message: 'Use callback in setState when referencing the previous state.'
  136. }]
  137. }, {
  138. code: [
  139. 'var Hello = React.createClass({',
  140. ' onClick: function() {',
  141. ' var {state, ...rest} = this',
  142. ' this.setState({value: state.value + 1})',
  143. ' }',
  144. '});'
  145. ].join('\n'),
  146. parserOptions: parserOptions,
  147. errors: [{
  148. message: 'Use callback in setState when referencing the previous state.'
  149. }]
  150. }, {
  151. code: [
  152. 'function nextState(state) {',
  153. ' return {value: state.value + 1}',
  154. '}',
  155. 'var Hello = React.createClass({',
  156. ' onClick: function() {',
  157. ' this.setState(nextState(this.state))',
  158. ' }',
  159. '});'
  160. ].join('\n'),
  161. parserOptions: parserOptions,
  162. errors: [{
  163. message: 'Use callback in setState when referencing the previous state.'
  164. }]
  165. }, {
  166. code: `
  167. var Hello = React.createClass({
  168. onClick: function() {
  169. this.setState(this.state, () => 1 + 1);
  170. }
  171. });
  172. `,
  173. parserOptions: parserOptions,
  174. errors: [{
  175. message: 'Use callback in setState when referencing the previous state.'
  176. }]
  177. }, {
  178. code: `
  179. var Hello = React.createClass({
  180. onClick: function() {
  181. this.setState(this.state, () => console.log(this.state));
  182. }
  183. });
  184. `,
  185. parserOptions: parserOptions,
  186. errors: [{
  187. message: 'Use callback in setState when referencing the previous state.'
  188. }]
  189. }, {
  190. code: [
  191. 'var Hello = React.createClass({',
  192. ' nextState: function() {',
  193. ' return {value: this.state.value + 1}',
  194. ' },',
  195. ' onClick: function() {',
  196. ' this.setState(nextState())',
  197. ' }',
  198. '});'
  199. ].join('\n'),
  200. parserOptions: parserOptions,
  201. errors: [{
  202. message: 'Use callback in setState when referencing the previous state.'
  203. }]
  204. }]
  205. });