React Hooks - ใช้ useState กับ just variables


12

React Hooks ให้เราใช้ตัวเลือก State และฉันจะเห็นการเปรียบเทียบ Hooks กับ Class-State เสมอ แต่สิ่งที่เกี่ยวกับ hooks และตัวแปรปกติบางอย่าง?

ตัวอย่างเช่น,

function Foo() {
    let a = 0;
    a = 1;
    return <div>{a}</div>;
}

ฉันไม่ได้ใช้ Hooks และมันจะให้ผลลัพธ์เหมือนกับ:

function Foo() {
    const [a, setA] = useState(0);
    if (a != 1) setA(1); // to avoid infinite-loop
    return <div>{a}</div>;
}

แล้วความแตกต่างคืออะไร? การใช้ Hooks มีความซับซ้อนมากขึ้นสำหรับกรณีนั้น ... ทำไมต้องเริ่มใช้มัน?


คุณกำลังเปรียบเทียบ 2 สิ่งที่แตกต่างกัน ฟังก์ชั่นที่สองพร้อม hooks มีความสามารถในการอัปเดตข้อมูล คนแรกไม่ได้ทำอะไรเลย คุณสามารถเริ่มต้นได้ด้วยlet a = 1; return <div>{a}</div>และคุณจะได้ผลลัพธ์เดียวกัน
Yathi

คำตอบ:


13

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

เปรียบเทียบตัวอย่างนี้:

function Foo() {
    const [a, setA] = useState(0);
    return <div onClick={() => setA(a + 1)}>{a}</div>;
}

function Foo() {
    let a = 0;
    return <div onClick={() => a + 1}>{a}</div>;
}

ในทั้งสองกรณีaการเปลี่ยนแปลงเมื่อคลิก แต่เฉพาะเมื่อคุณใช้useStateมุมมองอย่างถูกต้องแสดงaค่าปัจจุบันของ


ขอบคุณ! ดังนั้นถ้าฉันไม่ต้องการแสดงมุมมอง - วิธีเดียวในการจัดระเบียบข้อมูลของฉัน (อุปกรณ์ประกอบฉาก) ลงในอาร์เรย์ - ฉันสามารถใช้ 'ให้' มันเหมาะกับฉันฉันแค่อยากรู้ว่ามันโอเคและเป็นที่ยอมรับ
Moshe Nagar

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

อีกวิธีหนึ่งในการดูคำตอบนี้คือการคิดว่าในกรณีที่สองตัวแปรaจะถูกเก็บรวบรวมขยะหลังจากเสร็จสิ้นการดำเนินการในขณะที่ในครั้งแรกเพราะมันยกระดับuseStateมันจะรักษาคุณค่าของa
João Marcos Gris

เขายังคงสามารถใช้งานได้useRefถ้าเขาไม่ต้องการแสดงมุมมองอีกครั้ง คำถามยังคงอยู่ถ้าเขาควรใช้ตัวแปรท้องถิ่นหรืออ้างอิงปฏิกิริยา เช่นถ้าคุณมีการหมดเวลาที่คุณต้องการล้างหรือการร้องขอ HTTP ที่กำลังดำเนินการโดยใช้ axios คุณเก็บ timeout หรือ axios source ในตัวแปรหรือในการอ้างอิง React?
Tom

3
@Tom กฎทั่วไปใช้ vars เฉพาะที่สำหรับสถานะที่ได้รับ สำหรับสิ่งอื่นใช้useRef(ถ้าคุณไม่ต้องการแสดงผล) หรือuseState(ถ้าคุณต้องการแสดงผล) ในกรณีของตัวจับเวลาเนื่องจากเป็นผลข้างเคียงจึงควรเริ่มใช้useEffectตะขอ หากคุณต้องการtimerIdเพียงเพื่อวัตถุประสงค์ในการล้างข้อมูลคุณสามารถเก็บไว้ในตัวแปรโลคัลของตัวจัดการ หากคุณต้องการที่จะสามารถที่จะล้างจับเวลาจากสถานที่อื่น ๆ useRefในองค์ประกอบที่คุณควรใช้ การจัดเก็บtimerIdในตัวแปรโลคัลของคอมโพเนนต์จะเป็นข้อผิดพลาดเนื่องจาก vars โลคัลถูก "รีเซ็ต" ในแต่ละการแสดงผล
marzelin

1

สถานะการอัปเดตจะทำให้องค์ประกอบแสดงผลอีกครั้ง แต่ค่าในเครื่องไม่ใช่

ในกรณีของคุณคุณให้ค่าในองค์ประกอบของคุณ ซึ่งหมายความว่าเมื่อมีการเปลี่ยนแปลงค่าส่วนประกอบควรแสดงใหม่อีกครั้งเพื่อแสดงค่าที่อัปเดต

ดังนั้นจะใช้งานได้ดีuseStateกว่าค่าท้องถิ่นปกติ

function Foo() {
    let a = 0;
    a = 1; // there will be no re-render.
    return <div>{a}</div>;
}

function Foo() {
    const [a, setA] = useState(0);
    if (a != 1) setA(1); // re-render required
    return <div>{a}</div>;
}

0

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


0
function Foo() {
    const [a, setA] = useState(0);
    if (a != 1) setA(1); // to avoid infinite-loop
    return <div>{a}</div>;
}

เทียบเท่ากับ

class Foo extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            a: 0
        };
    }
    // ...
}

สิ่งที่useStateส่งคืนคือสองสิ่ง:

  1. ตัวแปรสถานะใหม่
  2. ตัวตั้งค่าสำหรับตัวแปรนั้น

ถ้าคุณโทรsetA(1)คุณจะโทรthis.setState({ a: 1 })และเรียกการแสดงผลอีกครั้ง


0

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

function App() {
  let a = 0; // reset to 0 on render/re-render
  const [b, setB] = useState(0);

  return (
    <div className="App">
      <div>
        {a}
        <button onClick={() => a++}>local variable a++</button>
      </div>
      <div>
        {b}
        <button onClick={() => setB(prevB => prevB + 1)}>
          state variable b++
        </button>
      </div>
    </div>
  );
}

แก้ไข serene-galileo-ml3f0

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