Skip to content

Commit 555dba8

Browse files
authored
Merge pull request #210 from hbmartin/ignores-stale-query-errors
applyErroredQueryResult now ignores stale/untracked query errors instead of creating a new error state
2 parents 174222d + c6735d3 commit 555dba8

3 files changed

Lines changed: 58 additions & 14 deletions

File tree

README.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,38 @@ This library is a TypeScript rewrite of [react-mentions](https://github.com/sign
660660
+ import { MentionsInput, Mention } from 'react-mentions-ts'
661661
```
662662

663+
### Automated Codemod
664+
665+
The package ships a [jscodeshift](https://github.com/facebook/jscodeshift) transform that handles most of the mechanical renames. After installing `react-mentions-ts`, run it against your source tree:
666+
667+
```bash
668+
npx jscodeshift \
669+
--parser=tsx \
670+
--extensions=tsx,ts,jsx,js \
671+
--transform=node_modules/react-mentions-ts/codemods/react-mentions-to-react-mentions-ts.cjs \
672+
src
673+
```
674+
675+
What the codemod rewrites automatically:
676+
677+
- Updates ESM `import` and CommonJS `require` statements (including namespace and destructured forms) from `react-mentions` to `react-mentions-ts`.
678+
- Renames `onChange``onMentionsChange` on `MentionsInput`. Inline arrow/function handlers have their positional parameters (`event`, `newValue`, `newPlainTextValue`, `mentions`) converted to the object payload; if the handler body references the event parameter, a `const event = trigger.nativeEvent` alias is prepended so existing code keeps working.
679+
- Renames `onBlur``onMentionBlur` on `MentionsInput`.
680+
- Rewrites `onAdd` on `Mention` from positional arguments (`id`, `display`, `startPos`, `endPos`) to the object payload.
681+
- Consolidates `allowSuggestionsAboveCursor` / `forceSuggestionsAboveCursor` into `suggestionsPlacement="auto"` / `"above"`.
682+
- Removes `allowSpaceInQuery` and `ignoreAccents` from `MentionsInput` and moves them onto each child `Mention`'s `trigger` via `makeTriggerRegex('@', { … })`, auto-importing the helper.
683+
- Removes the separate `regex` prop and wraps static `markup` strings with `createMarkupSerializer(...)`, auto-importing the helper.
684+
- When `onChange` or `onAdd` is passed as a bare identifier or member expression (e.g. `onChange={this.handleChange}`), wraps it in an adapter that calls the existing handler with the legacy positional arguments so the original implementation keeps working until you migrate it by hand.
685+
686+
The following cases are reported via `api.report(...)` (printed by jscodeshift) and must be migrated by hand:
687+
688+
- `data` providers that use the legacy `(query, callback) => …` signature must be rewritten to return an array or a promise (the codemod flags inline `data` functions that declare two or more parameters so you can confirm).
689+
- Dynamic values for `allowSpaceInQuery`, `ignoreAccents`, `allowSuggestionsAboveCursor`, or `forceSuggestionsAboveCursor` (e.g. `allowSpaceInQuery={someFlag}`) — these are removed with a warning and the equivalent trigger regex must be wired up manually.
690+
- `Mention` elements using `regex` when `markup` is missing or dynamic.
691+
- Callback attributes whose value is not an inline function, identifier, or member expression.
692+
693+
Review the diff and run your test suite after applying it.
694+
663695
### Renamed Props
664696

665697
| react-mentions | react-mentions-ts | Notes |

src/MentionsInputQueryState.spec.ts

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -350,24 +350,29 @@ describe('MentionsInputQueryState', () => {
350350
expect(nextState.focusIndex).toBe(0)
351351
})
352352

353-
it('defaults failed query metadata when no current query state exists', () => {
354-
const nextState = applyErroredQueryResult(
355-
{
356-
1: {
357-
queryInfo: { ...queryInfo, childIndex: 1 },
358-
results: [{ id: 'preserved', display: 'Preserved' }],
359-
},
353+
it('ignores stale errored query results without current query state', () => {
354+
const suggestions = {
355+
1: {
356+
queryInfo: { ...queryInfo, childIndex: 1 },
357+
results: [{ id: 'preserved', display: 'Preserved' }],
360358
},
361-
{},
359+
}
360+
const queryStates = {}
361+
362+
const nextState = applyErroredQueryResult(
363+
suggestions,
364+
queryStates,
362365
0,
363366
queryInfo,
364367
new Error('boom'),
365368
0
366369
)
367370

368-
expect(nextState.suggestions[1]?.results).toHaveLength(1)
369-
expect(nextState.focusIndex).toBe(0)
370-
expect(nextState.queryStates[0]?.ignoreAccents).toBe(false)
371+
expect(nextState).toEqual({
372+
suggestions,
373+
queryStates,
374+
focusIndex: 0,
375+
})
371376
})
372377

373378
it('defaults failed query accent metadata when the current query state omits it', () => {

src/MentionsInputQueryState.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -246,13 +246,20 @@ export const applyErroredQueryResult = <Extra extends Record<string, unknown>>(
246246
error: unknown,
247247
focusIndex: number
248248
): SuggestionsLifecycleState<Extra> => {
249+
if (!Object.hasOwn(currentQueryStates, childIndex)) {
250+
return {
251+
suggestions: currentSuggestions,
252+
queryStates: currentQueryStates,
253+
focusIndex,
254+
}
255+
}
256+
257+
const currentQueryState = currentQueryStates[childIndex]
249258
const suggestions = Object.fromEntries(
250259
Object.entries(currentSuggestions).filter(([key]) => Number(key) !== childIndex)
251260
) as SuggestionsMap<Extra>
252261
const suggestionsCount = countSuggestions(suggestions)
253-
const ignoreAccents = Object.hasOwn(currentQueryStates, childIndex)
254-
? (currentQueryStates[childIndex].ignoreAccents ?? false)
255-
: false
262+
const ignoreAccents = currentQueryState.ignoreAccents ?? false
256263

257264
return {
258265
suggestions,

0 commit comments

Comments
 (0)