RN JS 연습 - 3

아마 지금까지의 연습을 보면서 bind라는 부분에 대해 이해가 안되는 사람들이 많았을 것이라고 생각됩니다. 저도 그랬기 때문이지요.

그래서 bind에 대해 좀 더 연습을 해보도록 하겠습니다.

일단 bind란 어떤 함수를 실행할 때 그 함수 안에서의 this를 지정시켜주는 역할을 합니다.

this라는 것은 언제나 고정이 아닙니다. 그때 그때 바뀔 수 있고 있다.

이걸 인지하는 것이 가장 중요합니다.

한번 예를 볼까요?

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  TextInput,
  TouchableOpacity
} from 'react-native';

console.log('check')


class TodoItem extends Component {
  completeTodo(index) {
    let todos = this.state.todos
    todos[index].complete = !todos[index].complete
    this.setState({
      todos: todos,
    })
  }

  deleteTodo (index) {
    let todos = this.state.todos
    todos.splice(index, 1)
    this.setState({
      todos: todos,
    })
  }


  render() {
    let todoItem = this.props.item
    console.log(this.props)
    let index = this.props.index
    return(
      <View style={{flexDirection: 'row'}}>
        <Text style={todoItem.complete ? {textDecorationLine: 'line-through'} : {textDecorationLine: 'none'}}>
          {todoItem.context}
        </Text>
        <TouchableOpacity onPress={this.completeTodo.bind(this.props.todoApp, index)}>
          <Text>{todoItem.complete ? "---complete" : "---incomplete" }</Text>
        </TouchableOpacity>
        <TouchableOpacity onPress={this.deleteTodo.bind(this.props.todoApp, index)}>
          <Text>     delete </Text>
        </TouchableOpacity>
      </View>
    )
  }
}

class gitbookTest2 extends Component {
  componentWillMount() {
    this.setState({
      inputText: '',
      todos: [],
    })
  }

    addTodo() {
      let todoItem = {
        context: this.state.inputText,
        complete: false
      }
      let todos = this.state.todos
      todos.push(todoItem)
      this.setState({
        inputText: '',
        todos: todos,
      })
    }

  render() {
    return (
      <View style={styles.container}>
        <TextInput
          style={{height: 40,borderColor: 'gray', borderWidth: 1}}
          onChangeText={(text) => {
            this.setState({inputText: text})
          }}
          value={this.state.inputText}
          />
        <TouchableOpacity onPress={this.addTodo.bind(this)}>
          <Text>
            add Todo
          </Text>
        </TouchableOpacity>
        {
          this.state.todos.map((todoItem, index)=> {
            console.log(todoItem)
            console.log(index)
            return (
              <TodoItem item={todoItem} key={index} index={index} todoApp={this}/>
            )
          })
        }
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
});

AppRegistry.registerComponent('gitbookTest2', () => gitbookTest2);

이걸 한번 실행시켜보죠? 아마 그 전과 똑같이 실행이 될 것 입니다. 여기서 주목 해야하는 건

  completeTodo(index) {
    let todos = this.state.todos
    todos[index].complete = !todos[index].complete
    this.setState({
      todos: todos,
    })
  }

  deleteTodo (index) {
    let todos = this.state.todos
    todos.splice(index, 1)
    this.setState({
      todos: todos,
    })
  }

이 부분 입니다. 이 두 함수가 TodoItem 이라는 컴포넌트안에 들어 있습니다.

근데 todos의 state을 가지고 있는건 gitbookTest2라는 컴포넌트 입니다.

일반적으로 생각을 하면 TodoItem은 todos라는 state을 가지고 있지 않기 때문에 error가 생길 것 같지만 아닙니다. 그 이유는

<TouchableOpacity onPress={this.completeTodo.bind(this.props.todoApp, index)}>
          <Text>{todoItem.complete ? "---complete" : "---incomplete" }</Text>
</TouchableOpacity>
<TouchableOpacity onPress={this.deleteTodo.bind(this.props.todoApp, index)}>
          <Text>     delete </Text>
</TouchableOpacity>

이 안의 onPress을 봐볼까요?

onPress={this.completeTodo.bind(this.props.todoApp, index)}

여기서는 bind뒤에 this.props.todoApp 이라는 것을 사용하였네요. 그 뒤는 함수에 필요한 인자이구요. 그렇다면 이 this.props.todoApp이 무엇일까요?

<TodoItem item={todoItem} key={index} index={index} todoApp={this}/>

바로 여기서 todoApp={this}을 하였습니다. 즉 todoApp에 gitbookTest2 자기자신을 넣은것 이지요.

디버그창에서 확인하면 실제로 gitbookTest2가 들어가 있는 것을 확인 할 수 있습니다.

즉 bind(this.props.todoApp)을 통해서 우리는 completeTodo가 실행될때는 this가 gitbookTest2 를 의미한다는 것을 알 수 있습니다. this가 gitbookTest2이기 때문에 실제로 this.setState는 todoIte.setState가 아니라 gitbookTest2.setState을 의미하게 됩니다. 이렇게 우리는 todoItem 안에서 gitbookTest2의 state 값을 변경 할 수 있었습니다.

이제 어느정도 bind에 대한 이해가 잡혔을 것이라고 생각이 됩니다.

results matching ""

    No results matching ""