TIL #15 React (Summary)

Joshua Song / 송성현·2019년 12월 9일
0

이머시브_16

목록 보기
17/29

React

  • 프론트 엔드에서 유명한 프레임 워크. React, Angular, Vue 가 삼대천왕.
  • 페이스북이 만든 사용자 UI 구축을 위한 라이브러리.
  • 컴포넌트 기반 라이브러리. 여러 부분을 분할해서 코드의 재사용성과 유지보수성 증가.
  • 가상 DOM을 사용해 미리 최적화를 시켜주고 가상 돔은 바뀐 부분과 바뀌지 않은 부분을 자동으로 감지해 업데이트!
  1. Data Flow

    • 단방향 데이터 흐름. 부모에서 항상 자식으로 흐른다.
  2. Props

    • 내려오는 물줄기를 props라고 볼 수 있다. 상위 컴포넌트에서 하위 컴포넌트에 내려주는 데이터.
  3. State

    • 컵 안에 들어있는 물.
    • 컴포넌트가 갖는 상태. 객체의 형태로 컴포넌트 내에서 보관하고 관리.
    • class 컴포넌트로 작성. setState라는 메서드로 값을 변경할 수 있다.
      • render 함수가 다시 실행
  4. Life Cycle

    • 컴포넌트가 업데이트, 사라지거나 생성될 때 전 후로 보여지는 것.
      • 생성
        • constructor() => render() => componentDidMount()
      • 업데이트
        • state값 변경 => render() => componentDidUpdate()
    • class 컴포넌트로 작성. 함수형은 실행이 안된다.

JSX

  • syntax extension to JavaScript

  • 자바스크립트안에서 HTML 문법을 사용해 view를 구성할 수 있게 도와주는 문법

  • may look like a template language, but comes with the full power of JS.

  • produces React "elements". Can render them to the DOM.

  • helpful as a visual aid when working with UI inside the JS code (React)

  • React separates concerns(technologies) with loosely coupled units called "components" that contain both markup and logic.

  • Can put any valid JS expression inside the curly braces

    • ```js
      function formatName(user) {
      return user.firstName + ' ' + user.lastName;
      }
        const user = {
          firstName: 'Harper',
          lastName: 'Perez'
        };
        
        const element = (
          <h1>
            Hello, {formatName(user)}!
          </h1>
        );
        
        ReactDOM.render(
          element,
          document.getElementById('root')
        );
        ```
      Wrapping it in parentheses avoid automatic semicolon insertion.
  • JSX expressions become regular JS function calls and evaluate to JS objects.

    • ```js
      function getGreeting(user) {
      if (user) {
      return

      Hello, {formatName(user)}!

      ;
      }
      return

      Hello, Stranger.

      ;
      }
        ```
  • Can use quotes to specify string literals as attributes

    • const element = <div tabIndex="0"></div>;
          const element = <img src={user.avatarUrl}></img>;
    - JSX is closer to JS than to HTML. React DOM uses camelCase property naming convention. 
  • If a tag is empty, it can be closed immediately with />, like XML

const element = <img src={user.avatarUrl}/>
  • May contain children
     const element = (
       <div>
         <h1>Hello!</h1>
         <h2>Good to see you here.</h2>
       </div>
     );
- JSX prevents **Injection attack (XSS : cross-site-scripting)** because React DOM escapes any values embedded in JSX before rendering. Everything is converted to string beforehand. 

- Babel compiles JSX down to **React.createElement()** calls. Makes "React elements" and React reads these objects and use them to construct the DOM up to date. 
```js
const element - (
  <h1 className = "greeting">
  	Hello, world!
  </h1>
 );
//this is same as =>
const element = React.createElement(
  'h1',
  {className: 'greeting'},
  'Hello, world!'
)
**Output**:
const element = {
  type: 'h1',
  props: {
    className: 'greeting',
    children: 'Hello, world!'
    }
};

Rendering Elements

  • An element describes what you want to see on the screen. React DOM takes care of updating the DOM to match the React elements.
const element = <h1>Hello, world</h1>
  • This is how you would use **ReactDOM.render():

    	```js
    	const element = <h1>Hello, world</h1>
    ReactDOM.render(element, document.getElementById('root'));
    	```
  • React elements are immutable. Once created, element's children or attributes cannot be changed. Up to this point, the only way to update the UI is to create a new element and use ReactDOM.render().
    - React DOM compares the element and its children to the previous one and only applies the DOM updates when necessary.

Components and Props

  • Components allow UI to be split into independent and resusable pieces, like JS functions. They accept inputs(called "props") and return React elements.
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

Above is an example of a valid React component. It accepts a single "props"(properties) object argument with data and returns a React element. Such components are called "function components".
Below is an example of a ES6 class component.

class Welcome extends React.Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>
  }
}
  • Elements can also represent user-defined components:

const element = <Welcome name = "Sara" />;

When React sees an element represent user-defined component, it passes JSX attributes to this component as a single object. "Props"

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
//
const element = <Welcome name="Sara" />;
ReactDOM.render(
  element,
  document.getElementById('root')
);

Always start component names with a capital letter

  • Components can refer to other components in their output.

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
function App() {
  return (
    <div>
      <Welcome name="Sara" />
      <Welcome name="Cahal" />
      <Welcome name="Edite" />
    </div>
  );
}
ReactDOM.render(
  <App />,
  document.getElementById('root')
);
  • Props are Read-Only. Function is pure when it does not change its own input.

    All React components must act like pure functions

State and Lifecycle

  • Up to this point, ReactDOM.render() was the only way to change the rendered output.
function tick() {
  const element = (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {new Date().toLocaleTimeString()}.</h2>
    </div>
  );
  ReactDOM.render(
    element,
    document.getElementById('root')
  );
}
setInterval(tick, 1000);

The component above constantly updates the time through setInterval. What we want now is to make the Clock component(shows time and updates on its own) reusuable and encapsulated.

function Clock(props) {
  return (
    <div>
      <h1>Hello, world!</h1>
      <h2>It is {props.date.toLocaleTimeString()}.</h2>
    </div>
  );
}

function tick() {
  ReactDOM.render(
    <Clock date={new Date()} />,
    document.getElementById('root')
  );
}

setInterval(tick, 1000);

Now, the Clock component is encapsulated. But, it cannot set up a timer and update the UI every second. To do this, "state" needs to be added to the Clock component. Private and fully controlled by the component.
ES6 Version

class Clock extends React.Component {
  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.props.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

Clock is now defined as a class. render method will be called each time an update happens, but if we render into the same DOM node, only one version of Clock class will be used. Local state and lifecycle methods

Use this.state and constructor to create an instance then add local state to a Class

class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

ReactDOM.render(
  <Clock />,
  document.getElementById('root')
);
  • Adding Lifecycle Methods to a Class
    - Mounting: setting up a timer whenever the component is rendered to DOM. So depending on the function, it works like a scheduled alarm that carries out the function. componentDidMount() would be the lifecycle method.
    • Unmounting: clearing the timer whenever the DOM produced by component is removed. If the component is ever removed from the DOM, componentWillUnmount() lifecycle method will be called so the timer is stopper.
class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  componentWillUnmount() {
    clearInterval(this.timerID);
  }

  tick() {
    this.setState({
      date: new Date()
    });
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

ReactDOM.render(
  <Clock />,
  document.getElementById('root')
);
  1. When is passed to ReactDOM.render(), React calls the constructor of the Clock component as it initializes this.state with an object including the current time.
  2. React calls the render() method to print out what needs to be displayed on the screen. Then React updates the DOM to match the component's render output.
  3. When the ouput is inserted in the DOM, React calls the componentDidMonut() lifecycle method, which asks the browser to set up a timer to call tick() method once a second.
  4. Every second when the tick() method is called, this.setState changes the state, updating the state and calls the render() method so React knows what has changed. this.state.date will change accordingly and React updates the DOM with changes.
  5. If the Clock component is removed, React calls the componentWillUnmount() lifecycle method to stop the timer.
  • setState()
    - Do not modify state directly.

    ```js

    //wrong
    this.state.comment = "Hi";
    //correct
    this.setState({comment: "Hi"});

    ```
    this.state will only appear in the constructor. 
    
    - State Updates may be Asynchronous
    	- React may batch multiple setState() calls. this.props and this.state may be updated asynchronously. 
        ```js

    // Wrong
    this.setState({
    counter: this.state.counter + this.props.increment,
    });
    // Correct
    this.setState((state, props) => ({
    counter: state.counter + props.increment
    }));
    // Correct
    this.setState(function(state, props) {
    return {
    counter: state.counter + props.increment
    };
    });

    	```
    - State Updates are Merged
    	- When setState() is called, object provided is merged into the current state. However, independent variables can be updated independently with separate setState() calls. 
        ```js

    constructor(props) {
    super(props);
    this.state = {
    posts: [],
    comments: []
    };
    }
    componentDidMount() {
    fetchPosts().then(response => {
    this.setState({
    posts: response.posts
    });
    });
    //Two functions each udpates posts and comments.
    fetchComments().then(response => {
    this.setState({
    comments: response.comments
    });
    });
    }

    	```
  • The Data Flows Down
    - Neither parent nor chiildren components can know the state status of other components. State is often called local or encapsulated.

    • A component may choose to pass its state down as props to its child components.
    • "top-down" or "unidirectional" data flow.

Handling Events

  • React events are named using camelCase.
  • With JSX, you pass a function as the event handler, rather than a string.
//HTML
<button onclick="activateLasers()">
  Activate Lasers
</button>
//React
<button onClick={activateLasers}>
  Activate Lasers
</button>
  • You always have to use preventDefault() in React to prevent default behavior.
  • No need to call addEventListener to add listeners to a DOM element. Just provide a listener when the element is initially rendered.
  • When defining components using an ES6 class, event handler can be methods on the class.
  • bind (this) in a method if you refer to a method without ().
    - Either use publc class fields syntax or arrow function.
    ```js
    <button onClick={(e) => this.deleteRow(id, e)}>Delete Row
    <button onClick={this.deleteRow.bind(this, id)}>Delete Row
    ```

Conditional Rendering

  • Works the same way as if or the conditional operator does.
  • Can use variables to store elements.
  • May embed any expressions in JSX by wrapping them in curly brances. Includes && operator.
    - true && expression will appear the output and if it's false && expression, React will ignore and skip it.
  • Can also use 삼항연산자. condition ? true : false.
  • To hide component even though it was rendered by another component, return null.

Lists and Keys

  • Transforming arrays into lists of elements is nearly identical.
  • Can contain cllections of elements using JSX with {}.
const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((number) =>
  <li>{number}</li>
);
ReactDOM.render(
  <ul>{listItems}</ul>,
  document.getElementById('root')
);

배열에서 map을 통해 li 엘리먼트를 첨부해주고 ul에 렌더 해준다. 이 process를 함수로 만든 후 렌더해주는 첫번쩨 인자로 넣어 줄 수도 있다.

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    <li>{number}</li>
  );
  return (
    <ul>{listItems}</ul>
  );
}

const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
  <NumberList numbers={numbers} />,
  document.getElementById('root')
);

하지만 이 함수는 key가 없어서 리스트에 키를 포함해 줘야 한다고 나온다. 키는 special string sttribute로 리액트가 무슨 아이템이 변하거나, 추가되었거나, 제거되었는지 알아차리는데 도움을 준다.
키는 보통 그 아이템을 구분할때 바로 알아차릴 수 있는 string으로 사용한다. 없으면 index를 최후의 수단으로 사용해야 한다.

const todoItems = todos.map((todo) =>
  <li key={todo.id}>
    {todo.text}
  </li>
);
//고정 아이디가 없을 경우
const todoItems = todos.map((todo, index) =>
  // Only do this if items have no stable IDs
  <li key={index}>
    {todo.text}
  </li>
);

아이템의 순서가 바뀔수도 있어서 인덱스 값을 키로 설정하는 것은 권장하지 않는다. 만약 list의 아이템에 특정 키를 지정하지 않는다면 리액트는 자동으로 인덱스를 키 로 사용한다.

  • key can be used to extract components. Elements inside the map() call need keys
  • keys used in arrays should be unique among their siblings. But no need for them to be globally unique.

Forms

  • Form work in a similar way.
  • Controlled Component
    - in React, mutable state can only be updated with setState(). An input form element whose value is controlled(controls what happens in the form on subsequent user input) by React is called a "controlled component".
  • In React,
  • Select tag work similarly. Also, ,
  • The file input tag(user choose file then upload or manipulate by JS via the File API) is an uncontrolled component in React.
    <input type = "file" />
  • When handling multiple controlled input, add a name attribute to give freedome to handler function.
  • After specifying the value prop on a controlled component, user can't change the input. If the input is editable, the value may have been set to undefined or null.
  • Formik : validation, keeping tracking of the visited fields and handling form submission.

Lifting State Up

  • Lift the shared state up to their closest common ancestor.
  • Remove the local state of a lower component and move it into the higher one.
  • When the higher component owns the shared state, it becomes the "source of truth". It can maintain the consistency of state among different components. They will also be in sync.

Composition vs Inhertiance

  • Containment
    • It is common for some components to not know their children ahead of time. Special children prop can be used to pass children elements directly into their inputs.
  • Specialization
    • We think some components are "special cases" of other components. This can be achieved, where a "specific" component renders more"generic" one and configures it with props. Like inhertiance of methods! However, creating component inhertiance and hierarchies are not yet recommended.

Thinking in React

  1. Break the UI into a component hierarchy
    • single responsibility principle: a component should do one thing
  2. Build a Static Version in React
    • Will want to build components that reuse other components and pass data using props (a way of passing data from parent to child).
  3. Identify the Minimal (but complete) Representation of UI State
    • trigger changes to underlying data model using state.
    • Don't Repeat Yourself. figure out minimal representation of the state the application needs.
  4. Identify Where Your State Should Live
    • Identify which component mutates, or owns the state.
      - Identify every component that renders somehting based on that state.
      - Find a common owner component (가장 높은 조상)
      - Either the common owner or higher component should own the state.
      - If appropriate component to own the state can't be found, create a new component just for holding the state and add it somewhere higher than common owner component.
  5. Add Inverse Data Flow
    • Form components deep in the hierarchy need to update the state.
    • Data flow is pretty explicit.
    • Update needs to happen.
profile
Grow Joshua, Grow!

0개의 댓글