Goals

- Attach event handlers to components

- Bind to [this] with event handlers (and other aproach)

- Pass event handlers down as props to child components

- Undestand key props for mapping over data



## React event

- React use special reserved attributes for event handlings

- [All event list](https://ko.reactjs.org/docs/events.html)



## Method binding : the THIS keyword

- Without binding, you will lose the [this] context when you pass a function as a handler 

- So, we need [bind(this)] again

import React, { Component } from 'react';
import './WiseSquare.css';

class WiseSquare extends Component {

    constructor(props) {
        super(props);
        this.dispenseWisdom = this.dispenseWisdom.bind(this);
    }

    static defaultProps = {
        messages: [
            "you are so lazy",
            "sleep less",
            "read more book"
        ]
    };

    dispenseWisdom() {
        // make variable called messages, and it should be same as messages in this props
        let { messages } = this.props;

        // let message = [
        //     "you are so lazy",
        //     "sleep less",
        //     "read more book"
        // ];

        let rIdx = Math.floor(Math.random() * messages.length);
        console.log(messages[rIdx]);
    }
    render() {
        return (
            <div className='WiseSquare' onMouseEnter={this.dispenseWisdom}>
                <span>😝</span>
            </div>
        );
    }
}


export default WiseSquare;

 

- there is alternative way using [=()=>] 

import React, { Component } from 'react';
import './WiseSquare.css';

class ExperWiseSquare extends Component {

    static defaultProps = {
        messages: [
            "you are so lazy",
            "sleep less",
            "read more book"
        ]
    };

    // use arrow here, it's babel stage 2 magic
    // automatically add constructor and this keyword to bind
    dispenseWisdom = () => {
        console.log("this is :", this);
        // make variable called messages, and it should be same as messages in this props
        let { messages } = this.props;

        let rIdx = Math.floor(Math.random() * messages.length);
        console.log(messages[rIdx]);
    }

    render() {
        return (
            <div className='WiseSquare' onMouseEnter={this.dispenseWisdom}>
                <span>😝</span>
            </div>
        );
    }
}


export default ExperWiseSquare;



 

## Method binding with Arguments

- What if we need to pass arguments to an event handler?

- => use .bind inline and pass the argu as second argu after this 

- or arrow function and pass the argu

import React, { Component } from 'react';
import './ButtonList.css';

class ButtonList extends Component {
    static defaultProps = {
        colors: ['red', 'pink', 'orange', 'limegreen']
    };

    constructor(props) {
        super(props);
        this.state = { color: ' ' };
    }
    changeColor(boxColor) {
        this.setState({ color: boxColor });
    }

    render() {
        return (
            <div className="ButtonList" style={{ backgroundColor: this.state.color }}>
                {this.props.colors.map(color => {
                    const ColorBox = { backgroundColor: color };

                    //color변수를 bind의 두번째 변수로 넣어줌
                    // Both ways, we create new function
                    // onClick={()=>this.changeColor(color)} 도 가능
                    return (
                        <button style={ColorBox} onClick={this.changeColor.bind(this, color)}>
                            click me!
                        </button>
                    );
                })}
            </div>
        );
    }
}


export default ButtonList;




## Passing function to child components

import React, { Component } from 'react';
import BetterNumberItem from './BetterNumberItem';

class BetterNumberList extends Component {
    constructor(props) {
        super(props);
        this.state = { nums: [1, 2, 3, 4, 5] };
        this.remove = this.remove.bind(this);
    }

    remove(num) {
        this.setState(st => ({
            nums: st.nums.filter(n => n !== num)
        }));
    }

    render() {
        let nums = this.state.nums.map(n => (
            <BetterNumberItem key={n} value={n} remove={this.remove} />
        ));

        return (
            <div>
                <h1>Better Number List</h1>
                <ul>{nums}</ul>
            </div>
        );
    }
}


export default BetterNumberList;
import React, { Component } from 'react';

class BetterNumberItem extends Component {
    constructor(props) {
        super(props);
        this.handleRemove = this.handleRemove.bind(this);
    }
    handleRemove(evt) {
        this.props.remove(this.props.value);
    }
    render() {
        return (
            <li>
                {this.props.value}
                <button onClick={this.handleRemove}>X</button>
            </li>
        )
    }
}


export default BetterNumberItem;

 

- the idea : child are not stateful, but still need to tell parents to change state.

- How we send data "back up" to the Parent component?

 

    ### How data flows

    - Parent component defines a function

    - the function is passed as a prop to a child component

    - The child component invokes the prop

    - The parent function is called, usually setting new state

    - The parent component is re-rendered along with its children

 

    ### Where to bind?

    - Higher components is the better

    - If you need a parameter, pass it down to the child as props, then bind in parent and child

    - Avoid render-inline arrow functions / binding

    - Binding is only needed one time(in constructor!)

 

    - IF YOU GET STUCK! don't worry about performance too much. just write code that working and we can refactor later!

 

    ### Naming convention

    - For the consistency, try to follow the action/handleAction pattern:

        - parent : remove, add, open, toggle..

        - child : handleRemove, handleAdd, handleOpen, handleToggle..



## List and Key

- When mapping over data and returning components, you get a warning about keys for list items

- [KEY] is a special str attr to include when creating list of elements

    - keys help react identify which items have changed 

 

    ### Picking a key

    - Use str that uniquely identifies item

    - Most often we would use Ids from dataset as keys

    - We can use Idx, but not a good idea

    - 노드js에 쓸수있는 라이브러리 있음

'react' 카테고리의 다른 글

Handling multiple form : shopping list exercise  (0) 2020.06.14
React form control  (0) 2020.06.14
State exercise : coin flipper  (0) 2020.06.14
State exercise : lottery balls  (0) 2020.06.14
More State : data structure and designing state  (0) 2020.06.14