Skip to content

q.OnChange

This content is not available in your language yet.

GetPropertyChangedSignal 바인딩을 props의 배열 부분에 놓는 값으로 만든 것입니다. Tag생명주기 훅과 같은 자리에 놓입니다.

이 페이지의 심볼: q.OnChange(name, fn)

-- 설치 경로는 프로젝트 구성에 따라 다르다(00-installation 참고)
local Quad = require(<quad-base 모듈 경로>)
local QuadRoblox = require(<quad-roblox 모듈 경로>).QuadRoblox
local DModule = require(<quad-roblox 모듈 경로의 D 하위 모듈>) -- 클래스별 OnChange 유니언 타입
local q = Quad:UseProvider(QuadRoblox)
local D = q.D

시그니처

-- 생성 타입(quad-roblox/src/D). `PropTypesRead`는 D 스코프 전체의 "읽기 가능한
-- 프로퍼티 이름 → 타입" 맵이고, 클래스 간 타입이 충돌하는 이름은 any다.
export type OnChangeFn = <K>(
name: K & keyof<PropTypesRead>,
fn: (index<PropTypesRead, K>) -> ()
) -> OnChangeDescriptor<K>
export type OnChangeDescriptor<K> = { Name: K, Callback: (index<PropTypesRead, K>) -> () }

인자

이름 타입 설명
name 프로퍼티 이름 문자열 PropTypesRead의 키여야 한다 — 오타는 타입 에러
fn (newValue) -> () 그 프로퍼티가 바뀔 때 불린다. 파라미터 타입은 이름에서 추론된다

반환 — frozen 디스크립터 { Name, Callback }. 캐시가 없어 호출마다 새 값입니다.

예제

local size = q.Source(UDim2.fromScale(1, 0))
local box = D.Frame({
Size = size,
q.OnChange("AbsoluteSize", function(v: Vector2) -- 읽기 전용 프로퍼티도 된다
print(v.X, v.Y)
end),
q.OnChange("Visible", function(v) -- 주석을 생략해도 boolean으로 추론된다
local _: boolean = v
end),
})

동작

  • 콜백은 새 값을 받습니다 — 핸들러가 inst:GetPropertyChangedSignal(name)에 연결하고, 신호가 올 때 그 시점의 inst[name]을 읽어 넘깁니다. Deferred 신호 모드에서는 쓰기 한 번당 전달 한 번이고 값은 전달 시점에 읽힙니다.

  • 초기값도 콜백에 닿습니다. props의 배열 부분이 해시 부분보다 먼저 처리되므로, 같은 props에 적은 프로퍼티 쓰기가 이미 연결된 바인딩에 도착합니다.

    local seen = {}
    D.TextLabel({
    Text = "a", -- 해시 부분: 아래 바인딩이 연결된 뒤에 쓰인다
    q.OnChange("Text", function(v)
    table.insert(seen, v) -- seen[1] == "a"
    end),
    })
  • 같은 이름을 두 번 적으면 둘 다 연결됩니다. 해시 키 형태였다면 조용히 마지막 것만 남았을 자리라, 일부러 배열 값으로 만든 것입니다.

  • 배열 자리를 차지하지만 길이는 0입니다 — 물리 자식이 아니라서 형제 자식의 오프셋에 기여하지 않습니다.

  • State에 담아 반응형으로 바꿔 끼울 수 있습니다. State<T>는 불변이라 클래스별 유니언으로 캐스트해서 만듭니다.

    local desc = q.Source(q.OnChange("Visible", function(v: boolean) end) :: DModule.FrameOnChange)
    local box = D.Frame({ desc })

    그 자리에 q.None을 발행하면 연결이 끊기고, 새 디스크립터를 발행하면 하나만 다시 연결됩니다. 같은 값 dedup은 없습니다(Connect가 멱등이 아니라서, 재발행마다 Disconnect+Connect 한 번).

읽기 표면 — PropTypesRead

OnChange가 쓰는 이름 집합은 읽기 표면입니다. 그래서 D의 props 해시 키로는 쓸 수 없는 읽기 전용 프로퍼티도 여기서는 유효합니다.

q.OnChange("AbsoluteSize", function(v: Vector2) end) -- OK
q.OnChange("AbsolutePosition", function(v: Vector2) end) -- OK
q.OnChange("TextBounds", function(v: Vector2) end) -- OK

이름이 어느 클래스에도 없으면 타입 검사에서 걸립니다. 타입을 우회해 넘긴 이름은 런타임에 엔진이 자기 에러를 냅니다 — quad는 프로퍼티 존재 여부를 다시 검사하지 않습니다.

에러

상황 문구
이름이 문자열이 아니거나 "" OnChange: property name must be a non-empty string
콜백이 함수가 아님 OnChange: callback for "{name}" must be a function (got {typeof(fn)})

관련