useState () ใน React คืออะไร?


134

ฉันกำลังเรียนรู้แนวคิด hooks ใน React และพยายามทำความเข้าใจตัวอย่างด้านล่าง

import { useState } from 'react';

function Example() {
    // Declare a new state variable, which we'll call "count"
    const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

ตัวอย่างข้างต้นจะเพิ่มตัวนับในพารามิเตอร์ฟังก์ชันตัวจัดการเอง จะเกิดอะไรขึ้นถ้าฉันต้องการแก้ไขค่าการนับภายในฟังก์ชันตัวจัดการเหตุการณ์

พิจารณาตัวอย่างด้านล่าง

setCount = () => {
  //how can I modify count value here. Not sure if I can use setState to modify its value
  //also I want to modify other state values as well here. How can I do that
}

<button onClick={() => setCount()}>
  Click me
</button>

คุณยังสามารถดูในซอร์สโค้ดเพื่อทำความเข้าใจวิธีuseStateการใช้งาน นี่คือความหมายเป็นรุ่น 16.9
chemturion

คำตอบ:


150

React hooksเป็นวิธีใหม่ (ยังอยู่ระหว่างการพัฒนา) ในการเข้าถึงคุณสมบัติหลักของ react เช่นstateโดยไม่ต้องใช้คลาสในตัวอย่างของคุณหากคุณต้องการเพิ่มตัวนับโดยตรงในฟังก์ชันตัวจัดการโดยไม่ต้องระบุโดยตรงในonClickprop คุณ สามารถทำสิ่งที่ชอบ:

...
const [count, setCounter] = useState(0);
const [moreStuff, setMoreStuff] = useState(...);
...

const setCount = () => {
    setCounter(count + 1);
    setMoreStuff(...);
    ...
};

และ onClick:

<button onClick={setCount}>
    Click me
</button>

มาอธิบายสิ่งที่เกิดขึ้นในบรรทัดนี้อย่างรวดเร็ว:

const [count, setCounter] = useState(0);

useState(0)ส่งคืนทูเพิลโดยที่พารามิเตอร์แรกcountคือสถานะปัจจุบันของตัวนับและsetCounterเป็นวิธีการที่จะช่วยให้เราอัปเดตสถานะของตัวนับ เราสามารถใช้setCounterวิธีอัปเดตสถานะcountได้ทุกที่ - ในกรณีนี้เรากำลังใช้มันภายในsetCountฟังก์ชันที่เราสามารถทำสิ่งต่างๆได้มากขึ้น แนวคิดเกี่ยวกับ hooks คือเราสามารถทำให้โค้ดของเราทำงานได้มากขึ้นและหลีกเลี่ยงส่วนประกอบตามคลาสหากไม่ต้องการ / จำเป็น

ผมเขียนบทความที่สมบูรณ์เกี่ยวกับตะขอที่มีหลายตัวอย่าง (รวมถึงเคาน์เตอร์) เช่นนี้ codepenผมได้ใช้useState, useEffect, useContextและตะขอที่กำหนดเอง ฉันสามารถดูรายละเอียดเพิ่มเติมเกี่ยวกับวิธีการทำงานของ hooks กับคำตอบนี้ได้ แต่เอกสารประกอบทำได้ดีมากในการอธิบายรายละเอียดเกี่ยวกับตะขอเกี่ยวกับสถานะและตะขออื่น ๆ หวังว่าจะช่วยได้

UPDATE: ตะขอไม่ได้อีกต่อไปข้อเสนอตั้งแต่รุ่น16.8พวกเขากำลังในขณะนี้พร้อมที่จะใช้มีส่วนในการตอบสนองของเว็บไซต์ว่าคำตอบบางส่วนของคำถามที่พบบ่อย


2
การเปรียบเทียบที่ดียกเว้นว่า JavaScript ไม่มีประเภทข้อมูลทูเปิลในทางเทคนิค
goonerify

การมอบหมายที่ทำลายโครงสร้างถูกใช้เช่น tuple stackoverflow.com/a/4513061/6335029
NaveenDA

hooks async หรือไม่? ตอนใช้setSomethingถ้าลองใช้somethingโดยตรงดูว่ายังมีค่าเก่าอยู่ ...
Byron Coetsee

51

useStateเป็นหนึ่งใน react hooks ในตัวที่มีอยู่ใน0.16.7เวอร์ชัน

useStateควรใช้ภายในส่วนประกอบที่ใช้งานได้เท่านั้น useStateเป็นวิธีที่หากเราต้องการสถานะภายในและไม่จำเป็นต้องใช้ตรรกะที่ซับซ้อนมากขึ้นเช่นวิธีวงจรชีวิต

const [state, setState] = useState(initialState);

ส่งคืนค่าสถานะและฟังก์ชันที่จะอัปเดต

ในระหว่างการเรนเดอร์เริ่มต้นสถานะที่ส่งคืน (state) จะเหมือนกับค่าที่ส่งผ่านเป็นอาร์กิวเมนต์แรก (initialState)

ฟังก์ชัน setState ใช้เพื่ออัพเดตสถานะ ยอมรับค่าสถานะใหม่และกำหนดองค์ประกอบการแสดงผลใหม่

โปรดทราบว่าuseStateเบ็ดโทรกลับสำหรับการปรับปรุงรัฐทำงานแตกต่างกันthis.setStateกว่าส่วนประกอบ เพื่อแสดงความแตกต่างฉันเตรียมสองตัวอย่าง

class UserInfoClass extends React.Component {
  state = { firstName: 'John', lastName: 'Doe' };
  
  render() {
    return <div>
      <p>userInfo: {JSON.stringify(this.state)}</p>
      <button onClick={() => this.setState({ 
        firstName: 'Jason'
      })}>Update name to Jason</button>
    </div>;
  }
}

// Please note that new object is created when setUserInfo callback is used
function UserInfoFunction() {
  const [userInfo, setUserInfo] = React.useState({ 
    firstName: 'John', lastName: 'Doe',
  });

  return (
    <div>
      <p>userInfo: {JSON.stringify(userInfo)}</p>
      <button onClick={() => setUserInfo({ firstName: 'Jason' })}>Update name to Jason</button>
    </div>
  );
}

ReactDOM.render(
  <div>
    <UserInfoClass />
    <UserInfoFunction />
  </div>
, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>

วัตถุใหม่ถูกสร้างขึ้นเมื่อใช้การsetUserInfoโทรกลับ สังเกตว่าlastNameค่าคีย์หายไป เพื่อแก้ไขว่าเราสามารถส่งผ่านฟังก์ชันภายในuseStateได้

setUserInfo(prevState => ({ ...prevState, firstName: 'Jason' })

ดูตัวอย่าง:

// Please note that new object is created when setUserInfo callback is used
function UserInfoFunction() {
  const [userInfo, setUserInfo] = React.useState({ 
    firstName: 'John', lastName: 'Doe',
  });

  return (
    <div>
      <p>userInfo: {JSON.stringify(userInfo)}</p>
      <button onClick={() => setUserInfo(prevState => ({
        ...prevState, firstName: 'Jason' }))}>
        Update name to Jason
      </button>
    </div>
  );
}

ReactDOM.render(
    <UserInfoFunction />
, document.querySelector('#app'));
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.development.js"></script>

<div id="app"></div>

ซึ่งแตกต่างจากเมธอด setState ที่พบในคอมโพเนนต์คลาส useState จะไม่รวมอ็อบเจ็กต์อัพเดตโดยอัตโนมัติ คุณสามารถจำลองลักษณะการทำงานนี้ได้โดยการรวมแบบฟอร์มตัวอัปเดตฟังก์ชันเข้ากับไวยากรณ์การแพร่กระจายของวัตถุ:

setState(prevState => {
  // Object.assign would also work
  return {...prevState, ...updatedValues};
});

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับการuseStateดูเอกสารอย่างเป็นทางการ


2
ขอขอบคุณที่เพิ่มฟังก์ชันเป็นพารามิเตอร์ในตัวอย่าง
Juni Brosas

15

ไวยากรณ์ของuseStatehook นั้นตรงไปตรงมา

const [value, setValue] = useState(defaultValue)

ถ้าคุณไม่คุ้นเคยกับรูปแบบนี้ให้ไปที่นี่

ฉันขอแนะนำให้คุณอ่านเอกสารมีคำอธิบายที่ดีเยี่ยมพร้อมตัวอย่างจำนวนมาก

import { useState } from 'react';

function Example() {
    // Declare a new state variable, which we'll call "count"
    const [count, setCount] = useState(0);
  
  // its up to you how you do it
  const buttonClickHandler = e => {
   // increment
   // setCount(count + 1)
   
   // decrement
   // setCount(count -1)
   
   // anything
   // setCount(0)
  }
  

  return (
       <div>
          <p>You clicked {count} times</p>
         <button onClick={buttonClickHandler}>
             Click me
         </button>
      </div>
   );
 }


นี่ควรเป็นคำตอบที่ได้รับการยอมรับ กระชับและชัดเจนพร้อมข้อมูลอ้างอิงภายนอกที่ดี
varun

8

useStateเป็นหนึ่งในตะขอที่มีอยู่ใน React v16.8.0 โดยพื้นฐานแล้วจะช่วยให้คุณเปลี่ยนส่วนประกอบที่ไม่ระบุสถานะ / ใช้งานได้เป็นอย่างอื่นที่สามารถมีสถานะเป็นของตัวเองได้

ในระดับพื้นฐานจะใช้วิธีนี้:

const [isLoading, setLoading] = useState(true);

จากนั้นให้คุณเรียกการsetLoadingส่งผ่านค่าบูลีน เป็นวิธีที่ยอดเยี่ยมในการมีส่วนประกอบการทำงานที่ "มีสถานะ"


7

useState()เป็น React hook ตะขอทำให้สามารถใช้สถานะและความสามารถในการเปลี่ยนแปลงภายในส่วนประกอบของฟังก์ชัน

แม้ว่าคุณจะไม่สามารถใช้ hooks ในคลาสได้ แต่ก็สามารถใช้ hooks จากมันได้ นี่เป็นเครื่องมือที่ยอดเยี่ยมสำหรับการย้ายส่วนประกอบจากคลาสไปยังรูปแบบฟังก์ชัน นี่คือตัวอย่างที่สมบูรณ์:

สำหรับตัวอย่างนี้ฉันจะใช้ส่วนประกอบตัวนับ นี่ไง:

class Hello extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: props.count };
  }
  
  inc() {
    this.setState(prev => ({count: prev.count+1}));
  }
  
  render() {
    return <button onClick={() => this.inc()}>{this.state.count}</button>
  }
}

ReactDOM.render(<Hello count={0}/>, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id='root'></div>

เป็นส่วนประกอบของคลาสอย่างง่ายที่มีสถานะการนับและการอัปเดตสถานะทำได้โดยวิธีการ นี่เป็นรูปแบบทั่วไปในส่วนประกอบของคลาส สิ่งแรกคือการห่อด้วยส่วนประกอบของฟังก์ชันที่มีเพียงชื่อเดียวกันซึ่งจะมอบคุณสมบัติทั้งหมดให้กับส่วนประกอบที่ถูกรวมไว้ นอกจากนี้คุณต้องแสดงผลองค์ประกอบที่ห่อไว้ในการส่งคืนฟังก์ชัน นี่คือ:

function Hello(props) {
  class Hello extends React.Component {
    constructor(props) {
      super(props);
      this.state = { count: props.count };
    }

    inc() {
      this.setState(prev => ({count: prev.count+1}));
    }

    render() {
      return <button onClick={() => this.inc()}>{this.state.count}</button>
    }
  }
  return <Hello {...props}/>
}

ReactDOM.render(<Hello count={0}/>, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id='root'></div>

นี่เป็นส่วนประกอบเดียวกันโดยมีลักษณะการทำงานเหมือนกันชื่อเดียวกันและคุณสมบัติเดียวกัน ตอนนี้ให้ยกสถานะการนับเป็นส่วนประกอบของฟังก์ชัน นี่คือวิธีดำเนินการ:

function Hello(props) {
  const [count, setCount] = React.useState(0);
  class Hello extends React.Component {
    constructor(props) {
      super(props);
      this.state = { count: props.count };
    }

    inc() {
      this.setState(prev => ({count: prev.count+1}));
    }

    render() {
      return <button onClick={() => setCount(count+1)}>{count}</button>
    }
  }
  return <Hello {...props}/>
}

ReactDOM.render(<Hello count={0}/>, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js" integrity="sha256-3vo65ZXn5pfsCfGM5H55X+SmwJHBlyNHPwRmWAPgJnM=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js" integrity="sha256-qVsF1ftL3vUq8RFOLwPnKimXOLo72xguDliIxeffHRc=" crossorigin="anonymous"></script>
<div id='root'></div>

โปรดทราบว่าวิธีincนี้ยังคงมีอยู่มันจะไม่ทำร้ายใครในความเป็นจริงคือรหัสตาย นี่คือแนวคิดเพียงแค่ยกสถานะขึ้น เมื่อเสร็จแล้วคุณสามารถลบองค์ประกอบของชั้นเรียนได้:

function Hello(props) {
  const [count, setCount] = React.useState(0);

  return <button onClick={() => setCount(count+1)}>{count}</button>;
}

ReactDOM.render(<Hello count={0}/>, document.getElementById('root'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js" integrity="sha256-3vo65ZXn5pfsCfGM5H55X+SmwJHBlyNHPwRmWAPgJnM=" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js" integrity="sha256-qVsF1ftL3vUq8RFOLwPnKimXOLo72xguDliIxeffHRc=" crossorigin="anonymous"></script>

<div id='root'></div>

แม้ว่าสิ่งนี้จะทำให้สามารถใช้ hooks ภายในส่วนประกอบของคลาสได้ แต่ฉันไม่แนะนำให้คุณทำเช่นนั้นยกเว้นว่าคุณจะย้ายข้อมูลเหมือนที่ฉันทำในตัวอย่างนี้ การผสมฟังก์ชันและส่วนประกอบของคลาสจะทำให้การจัดการสถานะไม่เป็นระเบียบ ฉันหวังว่านี่จะช่วยได้

ขอแสดงความนับถืออย่างสูง


7

useState () เป็นตัวอย่าง React hook ในตัวที่ให้คุณใช้สถานะในส่วนประกอบการทำงานของคุณ สิ่งนี้ไม่สามารถทำได้ก่อน React 16.7

ฟังก์ชัน useState เป็นตะขอในตัวที่สามารถนำเข้าจากแพ็กเกจปฏิกิริยา ช่วยให้คุณสามารถเพิ่มสถานะให้กับส่วนประกอบที่ใช้งานได้ การใช้ตะขอ useState ภายในส่วนประกอบฟังก์ชันคุณสามารถสร้างสถานะโดยไม่ต้องเปลี่ยนไปใช้ส่วนประกอบของคลาส


5

Hooks เป็นคุณสมบัติใหม่React v16.7.0-alpha useStateคือ "Hook" useState()ตั้งค่าเริ่มต้นของตัวแปรใด ๆ และจัดการในองค์ประกอบของฟังก์ชัน (ฟังก์ชัน PureComponent) ex : const [count, setCount] = useState(0);ตั้งค่าเริ่มต้นของการนับ 0 และคุณสามารถใช้setCountเพื่อincrementหรือdecrementค่า onClick={() => setCount(count + 1)}เพิ่มค่าการนับ DOC


5

ขอบคุณ loelsonk ฉันทำเช่นนั้น

const [dataAction, setDataAction] = useState({name: '', description: ''});

    const _handleChangeName = (data) => {
        if(data.name)
            setDataAction( prevState  => ({ ...prevState,   name : data.name }));
        if(data.description)
            setDataAction( prevState  => ({ ...prevState,   description : data.description }));
    };
    
    ....return (
    
          <input onChange={(event) => _handleChangeName({name: event.target.value})}/>
          <input onChange={(event) => _handleChangeName({description: event.target.value})}/>
    )


2

useState เป็นตะขอที่ให้คุณเพิ่มสถานะให้กับส่วนประกอบที่ใช้งานได้ ยอมรับอาร์กิวเมนต์ซึ่งเป็นค่าเริ่มต้นของคุณสมบัติของรัฐและส่งคืนค่าปัจจุบันของคุณสมบัติของรัฐและวิธีการที่สามารถอัปเดตคุณสมบัติของรัฐนั้นได้
ต่อไปนี้เป็นตัวอย่างง่ายๆ:
import React, {useState} from react
function HookCounter {
const [count, stateCount]= useState(0)
return(
<div>
<button onClick{( ) => setCount(count+1)}> count{count} </button>
</div>
)
}

useState ยอมรับค่าเริ่มต้นของตัวแปรสถานะซึ่งเป็นศูนย์ในกรณีนี้และส่งคืนคู่ของค่า ค่าปัจจุบันของสถานะถูกเรียกว่า count และเมธอดที่สามารถอัพเดตตัวแปรสถานะถูกเรียกว่า setCount

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.