Encapsulating data operation

A simple example

//index.js import React, { useRef, useState, useEffect } from "react"; import ReactDOM from "react-dom"; import useList from "./hooks/useList"; function App() { const { list, setList } = useList(); return ( <div className="App"> <h1>List</h1> {list ? (< ol > {list. The map (item = > (< li key = {item. Id} > {item. The name} < / li >))} < / ol >) : (" loading..." )} </div> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);Copy the code
//useList.js import { useState, useEffect } from "react"; const useList = () => { const [list, setList] = useState(null); useEffect(() => { ajax("/list").then(list => { setList(list); }); } []); // [] Make sure to only run return {list: list, setList: setList} for the first time; }; export default useList; function ajax() { return new Promise((resolve, reject) => { setTimeout(() => { resolve([ { id: 1, name: "Frank" }, { id: 2, name: "Jack" }, { id: 3, name: "Alice" }, { id: 4, name: "Bob" } ]); }, 2000); }); }Copy the code

In uselist. js, export a useList function. We put data initialization, Ajax, and setList in this function. As long as I call my custom function outside, I can get the interface to read and write the list.

Details: Use useState to initialize data. UseEffect to send an AJAX request on the first rendering, setList on success. Then return the read/write interface.

In our App, we just call useList() to get the data.

A custom hook is to put all the logic into one function. Get the read/write interface of the data by calling the function.

Effect:

Sweet example – add, delete, change and check

//index.js import React, { useRef, useState, useEffect } from "react"; import ReactDOM from "react-dom"; import useList from "./hooks/useList"; function App() { const { list, deleteIndex } = useList(); return ( <div className="App"> <h1>List</h1> {list ? ( <ol> {list.map((item, index) => ( <li key={item.id}> {item.name} <button onClick={() => { deleteIndex(index); }} > x </button> </li>)) </ol>) : )} </div> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement);Copy the code
//useList.js import { useState, useEffect } from "react"; const useList = () => { const [list, setList] = useState(null); useEffect(() => { ajax("/list").then(list => { setList(list); }); } []); // [] Make sure to run only the first time return {list: list, addItem: name => {setList([...list, {id: math.random (), name: name}]); }, deleteIndex: index => { setList(list.slice(0, index).concat(list.slice(index + 1))); }}; }; export default useList; function ajax() { return new Promise((resolve, reject) => { setTimeout(() => { resolve([ { id: "1", name: "Frank" }, { id: "2", name: "Jack" }, { id: "3", name: "Alice" }, { id: "4", name: "Bob" } ]); }, 2000); }); }Copy the code

Return the corresponding function logic.

You can even use Context in custom hooks

UseState only says it can’t run inside an if, but it doesn’t say it can’t run inside a function, as long as the function runs inside a function component.