Skip to main content

2 posts tagged with "Refs"

View All Tags

· 2 min read
Vũ Anh Tú

Ý tưởng chính của component

  • Component nên được tạo nên từ các thành phần nhỏ nhất là các component nhỏ hơn nữa được custom từ DOM của HTML, tuy nhiên được custom theo từng UI Ví dụ dưới đây là component được custom từ input: Ở đây sự dụng component custom như là một Node của HTML tuy nhiên có thể style theo từ dự án
import React from "react";

const Input = (props) => {
return (
<>
<input placeholder="Custom input" {...props}/>
</>
)
}

export default Input;

Các cách để tạo ra một basis

1. Sử dựng Style component
  • Có thể dựng component, truyền props để xây dựng UI
import styled from 'style-component'

const Button = styled.button`
/* Adapt the colors based on primary prop */
background: ${props => props.primary ? "palevioletred" : "white"};
color: ${props => props.primary ? "white" : "palevioletred"};

font-size: 1em;
margin: 1em;
padding: 0.25em 1em;
border: 2px solid palevioletred;
border-radius: 3px;
`;

render(
<div>
<Button>Normal</Button>
<Button primary>Primary</Button>
</div>
);
2. Sử dụng REF => Can thiệp sâu hơn vào API của DOM
  • Như là ở một article nào đó tôi đã nói kĩ về refs, và các cách để ứng dụng refs vào một component. Ứng dụng của refs là rất thực tiễn cho các component nhỏ, cần can thiệp sâu vào các API của element DOM ví dụ như: focus(), blur(), click(), select(), setSelectionRange(), setRangeText() setCustomValidity(), checkValidity(), reportValidity()

Create component

export default class InputClass extends React.Component {
state = {
test: "test"
}
showLog = () => {
console.log("show log");
};
render() {
return (
<>
<div>Class input component</div>
<div>Test: {this.state.test}</div>
<input placeholder="class input" />
</>
);
}
}

const InputRef = React.forwardRef((props, ref) => (

<>
<div>Custom input component using forward re</div>
<input placeholder="custom ref input" ref={ref} {...props}/>
</>

))


>Using
```javascript
function App() {
let customRefInput = React.createRef();
let classInput = React.createRef();
const [inputValue, setInputValue] = useState("");
return (
<div className="App">
<h1>Hello React 17</h1>
<h2>Start learing REF react</h2>
<Input
value={inputValue}
onChange={e => setInputValue(e.target.value)}
ref={node => console.log("input 1", node)}
/>
<InputRef ref={node => (customRefInput = node)} />
<InputClass ref={node => (classInput = node)} />
<div>
<button onClick={() => customRefInput.focus()}>Focus</button>
<button onClick={() => customRefInput.blur()}>Blur</button>
<button onClick={() => classInput.setState({ test: "test" })}>
Reset state
</button>
<button onClick={() => classInput.setState({ test: "Change test" })}>
Set state
</button>
</div>
</div>
);
}

· 4 min read
Vũ Anh Tú

Refs là gì:

  • Theo react official: React supports a special attribute that you can attach to any component (DOM node and component). The ref attribute can be an object created by React.createRef() function or a callback function, or a string (in legacy API). When the ref attribute is a callback function, the function receives the underlying DOM element or class instance (depending on the type of element) as its argument. This allows you to have direct access to the DOM element or component instance. Use refs sparingly. If you find yourself often using refs to “make things happen” in your app, consider getting more familiar with top-down data flow.
  • Refs là một thuộc tính đặc biệt có thể attach vào bất kể một component nào (DOM node and component), thuộc tính ref có thể được tạo ra bằng React.createRef(), hoặc dùng function (node) => refName = node, hoặc đơn giản là string

    1. String refs: Là cách cũ nhất để tạo ra một refs và sẽ bị loại bỏ trong tương lai

    // String
    export default class index extends React.Component {
    constructor() {
    super();
    this.state = {sayings: "" };
    }
    update(e) {
    this.setState({sayings: this.refs.input.value});
    }

    render() {
    return (
    <div>
    Bob says <input type="text" ref="btalks" onChange={this.update.bind(this)} />
    {this.state.sayings}
    </div>
    );
    }
    }

    If you’re currently using this.refs.textInput to access refs, we recommend using either the callback pattern or the createRef API instead.

    2. Callback refs

    class MyComponent extends React.Component {
    constructor(props) {
    super(props);
    this.state = { uppercase: false };
    }

    toggleInputCase = () => {
    const isUpper = this.state.uppercase;
    // Accessing the ref using this.inputField
    const value = this.inputField.value;
    this.inputField.value =
    isUpper
    ? value.toLowerCase()
    : value.toUpperCase();
    this.setState({ uppercase: !isUpper });
    }
    render() {
    return (
    <div>
    {/* Creating a callback ref and storing it in this.inputField */}
    <input type="text" ref={elem => this.inputField = elem} />
    <button type="button" onClick={this.toggleInputCase}>
    Toggle Case
    </button>
    </div>
    );
    }

    }

    3. Using React.createRef()

    class MyComponent extends React.Component {
    constructor(props) {
    super(props);
    this.myRef = React.createRef();
    }
    render() {
    return <div ref={this.myRef} />;
    }
    }
 

#### 4. Some technical of Refs
##### a. Forward refs:
* Là kĩ thuật tự động truyền ref qua một component => đến một trong các component con của nó
```javascript
function FancyButton(props) {
return (
<button className="FancyButton" {...props}>
{props.children}
</button>
);
}
  • Xét vd trên: đây là các thông thường để tạo một custom component từ element, có thể lấy được hết các props từ cha đến thằng input nằm bên trong, tuy nhiên những API như focus(), blur(), click(), select(), setSelectionRange(), setRangeText() setCustomValidity(), checkValidity(), reportValidity() thì forward ref sẽ giải quyết đc vấn đề này:
import React from 'react'

const InputRef = React.forwardRef((props, ref) => (
<>
<input placeholder="custom ref input" ref={ref} {...props}/>
</>
))

export default InputRef

// Using
function App() {
let customRefInput = React.createRef();
const [inputValue, setInputValue] = useState("");
return (
<div className="App">
<h1>Hello React 17</h1>
<h2>Start learing REF react</h2>
<div>Custom input component</div>
<Input value={inputValue} onChange={e => setInputValue(e.target.value)} />
<div>Custom input component using forward ref</div>
<InputRef ref={node => (customRefInput = node)} />
<div>
{/*Click button to focus ref input */}
<button onClick={() => customRefInput.focus()}>Focus</button>
</div>
</div>
);
}
b. Refs for class component
  • Mỗi class component (function component không có) cũng có thuộc tính ref, ref trỏ đến đối tượng (instance) được tạo ra từ class component Từ đây có thể access vào các method có sẵn của component được gán ref cũng như các method tự định nghĩa, ví dự trong tình huống này là method showLog

export default class InputClass extends React.Component {
showLog = () => {
console.log("show log");
};
render() {
return (
<>
<input placeholder="class input" />
</>
);
}
}


function App() {
let customRefInput = React.createRef();
let customInput = React.createRef();
const [inputValue, setInputValue] = useState("");
return (
<div className="App">
<h1>Hello React 17</h1>
<h2>Start learing REF react</h2>
<Input
value={inputValue}
onChange={e => setInputValue(e.target.value)}
// Không được show lo
ref={node => console.log("input 1", node)}
/>
<InputRef ref={node => console.log("input 2", node)} />
<InputClass ref={node => console.log("input 3", node)}/>
</div>
);
}
  • Và đây là implememt
function App() {
let customRefInput = React.createRef();
let classInput = React.createRef();
const [inputValue, setInputValue] = useState("");
return (
<div className="App">
<h1>Hello React 17</h1>
<h2>Start learing REF react</h2>
<Input
value={inputValue}
onChange={e => setInputValue(e.target.value)}
ref={node => console.log("input 1", node)}
/>
<InputRef ref={node => (customRefInput = node)} />
<InputClass ref={node => (classInput = node)} />
<div>
<button onClick={() => customRefInput.focus()}>Focus</button>
<button onClick={() => customRefInput.blur()}>Blur</button>
<button onClick={() => classInput.setState({ test: "test" })}>
Reset state
</button>
<button onClick={() => classInput.setState({ test: "Change test" })}>
Set state
</button>
</div>
</div>
);
}