Repository navigation
refactor: use x, defaultX and onXChange for state props - #983
rohanchkrabrty wants to merge 4 commits into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
commit: |
d888724 to
5b27067
Compare
A JSON copy of the reported query no longer resets the filters. Server mode reports the mount query once under StrictMode. onQueryChange runs before the state update.
A controlled DatePicker can start empty with value={null}. onValueChange runs before the state update.
d7c976e to
de53b19
Compare
|
|
||
| /** Compares two wire queries by value, so a JSON copy matches its source. */ | ||
| export const isSameQuery = (a?: DataViewQuery, b?: DataViewQuery): boolean => | ||
| JSON.stringify(a) === JSON.stringify(b); |
There was a problem hiding this comment.
suggestion: JSON.stringify depends on key order, so a parent that rebuilds the query (say from URL params, { filters, sort } vs { sort, filters }) won't match.
That falls through to the reset path, which drops filter chips that have no value yet, the case this check exists to protect.
Could we compare in an order-independent way, for example by sorting keys before stringifying?
| key={filter.name} | ||
| label={filter.label} | ||
| value={filter.value ?? undefined} | ||
| value={filter.value ?? ''} |
There was a problem hiding this comment.
suggestion: The ?? '' here keeps the chip controlled from its first render, but DataTable's copy (data-table/components/filters.tsx:151) still passes value={filter.value}.
I rendered a FilterChip with value={undefined} and then value="abc": Base UI logs "changing the uncontrolled value state of FilterChip to be controlled", and the input stays empty.
Could we add the same guard on the DataTable side?
| fields: DataViewField<TData>[]; | ||
| /** Initial query. Transformed to the internal shape on mount. */ | ||
| /** The query (controlled). */ | ||
| query?: DataViewQuery; |
There was a problem hiding this comment.
question: DataTable keeps a read-once query (its JSDoc says "Initial query") and onTableQueryChange, so after this PR the same prop name means "controlled" on DataView and "first value" on DataTable. Is DataTable getting the same change in a follow-up, or should its docs call out the difference?
| (nextIndex: number) => { | ||
| onStepIndexChangeRef.current?.( | ||
| nextIndex, | ||
| createChangeDetails('none', undefined, { |
There was a problem hiding this comment.
nit: Every step change reports reason none with a placeholder event, including Next and Back clicks.
Sidebar and ChatPanel pass trigger-press with the click event (from #979), so could the buttons pass theirs through setIndex, keeping none for imperative calls?
Summary
x,defaultXandonXChange. SelectsearchValue,defaultSearchValue,onSearchbecomeinputValue,defaultInputValue,onInputValueChange. DatePicker and RangePickeronSelectbecomesonValueChange. TouronStepChangebecomesonStepIndexChange, with the step indetails.step. DataViewonTableQueryChangebecomesonQueryChange.queryand FilterChipvaluewere read on the first render only. They are now controlled with Base UIuseControlled, anddefaultQueryanddefaultValueset the first value. DatePickervaluealso moves touseControlled, andvalue={null}is a controlled empty date.operationanddefaultOperation. DataView passes each filter'soperatorto its chip, so a query withoperator: 'neq'shows "is not".eventDetails. DatePicker, RangePicker, Tour, DataView and FilterChiponOperationChangepassdetailsfromcreateChangeDetails.Stacked on #979. Retarget to
mainafter it merges.Decisions
eventDetails.isCanceled.onOperationChange, now(operation, details).onValueChangekeepsdetails.operationfrom feat: pass a details object to change callbacks #979. Thedetails.reasoncomes from the operation Select.queryfrom outside replaces it only when the two differ. A copy of the reported query, for example a JSON copy from the URL, counts as the same query, so a new empty filter chip stays. Aquerychange from outside does not callonQueryChange.onQueryChangein client mode too, so a controlled query works in both modes. Server mode still calls it once on mount, asonTableQueryChangedid, also under StrictMode.details.reasonisnone, because the call runs after the state change.queryfollows React's controlled rule: if the parent does not pass the new query back, the view returns to thequeryprop.onValueChangeonly when the typed date differs from the value. A day click passes reasonitem-pressand a typed date passesinput-change.defaultOperationfalls back to the first operation, as before. FilterChip keeps the typed text of anumbercolumn, so1.and-stay editable under a controlledvalue.docs/rfcs/003anddocs/V1-migration.mdkeep the old names, since they record earlier releases. DataTable keepsqueryandonTableQueryChange.Builds on merged PRs
valueandsearchValue, RangePickervalueand DataViewviewtouseControlled. This PR renames Select'ssearchValuestate toinputValueand keeps refactor: use base ui useControlled for controlled state #966'suseControlledfor RangePicker.inputValue,defaultInputValueandonInputValueChangeto Base UI.inputValueon Combobox, so it needs no change.