코틀린으로 리액트 프로그래밍을 하시기 전에
수신 객체 지정 람다
와프로퍼티 위임(by)
에 대해서 미리 선행하시는 걸 추천드립니다.
@JsExport
class TestComponent : RComponent<RProps, RState>() {
override fun RBuilder.render() {
div {
a {
+"Hello, world!"
}
}
}
}
컴포넌트를 생성하기 위해서는 RComponent
를 상속받는 클래스를 만들면 됩니다.
그리고 RBuilder.render()
확장 함수를 오버라이딩하고
HTML Kotlin DSL
을 이용하여 마음껏 코드를 작성하시면 됩니다.
@JsExport
class TestComponent : RComponent<RProps, RState>() {
override fun RBuilder.render() {
div {
aComponent {}
}
}
}
@JsExport
class AComponent : RComponent<RProps, RState>() {
override fun RBuilder.render() {
a {
+"My name is jaychy-yy!"
}
}
}
fun RBuilder.aComponent(handler: RProps.() -> Unit): ReactElement {
return child(AComponent::class) {
this.attrs(handler)
}
}
리액트를 제대로 사용하기 위해서는 한 컴포넌트에서 다른 컴포넌트를 가져와 조립할 수 있어야합니다.
RBuilder.render()
는 수신 객체 지정 람다로 구현되어 있기 때문에
RBuilder.aComponent()
처럼 RBuilder
의 함수로 확장해야 합니다.
만약 이후에 소개할 props
가 필요없을 경우 다음과 같이 handler
를 제거하여도 무방합니다.
fun RBuilder.aComponent(): ReactElement {
return child(AComponent::class) {}
}
external interface AComponentProps : RProps {
var name: String
}
@JsExport
class AComponent : RComponent<AComponentProps, RState>() {
override fun RBuilder.render() {
a {
+"My name is ${props.name}!"
}
}
}
fun RBuilder.aComponent(handler: AComponentProps.() -> Unit): ReactElement {
return child(AComponent::class) {
this.attrs(handler)
}
}
props
를 사용하기 위해서는 RProps
를 상속 받는 external interface
를 생성하면 됩니다.
내부 프로퍼티는 임의로 라이브러리에서 생성 후 초기화 되기 때문에
반드시 var
로 선언해야 합니다.
이제 AComponent
를 사용하는 측에서는 attrs {}
을 통해 props
를 전달할 수 있습니다.
@JsExport
class TestComponent : RComponent<RProps, RState>() {
override fun RBuilder.render() {
div {
aComponent {
attrs {
name = "jaychy-yy"
}
// attrs.name = "jaychy-yy" // 이렇게도 할 수 있습니다.
}
}
}
}
data class AComponentState(
val test: String,
) : RState
@JsExport
class AComponent : RComponent<AComponentProps, AComponentState>() {
init {
state = AComponentState("")
}
override fun RBuilder.render() {
a {
+"My name is ${props.name}!"
}
}
}
컴포넌트의 상태를 저장하기 위해서는 저장할 공간을 data class
로 표현합니다.
사용할 땐 state.test
형식으로 사용하고
상태를 변경하기 위해서는 setState()
메소드를 사용합니다.
또한 초기상태를 init block
에서 진행할 수 있습니다.
object MyStyles : StyleSheet("MyStyles", isStatic = true) {
val name by css {
fontSize = 20.px
color = rgb(0, 0, 0)
backgroundColor = Color.white
}
}
스타일시트를 만드는 방법은 위와 같습니다.
생긴 것은 styled-component
와 비슷해서 쉽게 사용할 수 있을 것 같습니다.
또한 보통 object
로 선언하여 싱글톤으로 만들어 효율적으로 사용하게 합니다.
@JsExport
class AComponent : RComponent<AComponentProps, AComponentState>() {
init {...}
override fun RBuilder.render() {
styledA {
css {
+MyStyles.name
}
+"My name is ${props.name}!"
}
}
}
스타일을 적용하기 위해서는 태그를 styled...
태그로 변경하여야 합니다.
styled...
태그 안에는 css()
함수를 사용할 수 있도록 CSSBuilder
가 생성됩니다.
+로 연결되는 것은 내부적으로 연산자 오버로딩이 되어 있기 때문입니다.
- kotlin/js - 1.5.10
- kotlin react - 17.0.1-pre.148-kotlin-1.4.30
- kotlin react dom - 17.0.1-pre.148-kotlin-1.4.30
- kotlin styled - 5.2.1-pre.148-kotlin-1.4.30
src
ㄴ main
ㄴ kotlin
ㄴ MainStyles.kt ] - Styled Component 형식으로 정리한 스타일 객체
ㄴ ToDoListStyles.kt ]
ㄴ client.kt - 이후에 나오는 컴포넌트들을 root 아래에 두기 위한 기초 컴포넌트
ㄴ main.kt - ToDoList의 메인 화면 컴포넌트
ㄴ toDo.kt - ToDoList 내부의 ToDo를 담당하는 컴포넌트
ㄴ toDoInsertion.kt - ToDo를 생성하기 위한 input 컴포넌트
ㄴ toDoList.kt - ToDoList의 몸체
ㄴ resources
ㄴ index.html - 빌드 후 생성된 kotlin-react.learn.js 스크립트를 실행할 기초 HTML