ตอบสนองฟังก์ชั่น onClick fires เมื่อแสดงผล


212

ฉันส่งค่า 2 ค่าไปยังคอมโพเนนต์ชายน์:

  1. รายการของวัตถุที่จะแสดง
  2. ฟังก์ชั่นลบ

ฉันใช้ฟังก์ชั่น. map () เพื่อแสดงรายการวัตถุของฉัน (เช่นในตัวอย่างที่ให้ไว้ในหน้าการตอบสนองต่อการกวดวิชา) แต่ปุ่มในองค์ประกอบนั้นจะทำการonClickทำงานของฟังก์ชั่นในการแสดงผล รหัสของฉันมีลักษณะเช่นนี้:

module.exports = React.createClass({
    render: function(){
        var taskNodes = this.props.todoTasks.map(function(todo){
            return (
                <div>
                    {todo.task}
                    <button type="submit" onClick={this.props.removeTaskFunction(todo)}>Submit</button>
                </div>
            );
        }, this);
        return (
            <div className="todo-task-list">
                {taskNodes}
            </div>
        );
    }
});

คำถามของฉันคือ: เหตุใดonClickฟังก์ชั่นนี้จึงใช้ไฟในการเรนเดอร์และทำไม่ได้?

คำตอบ:


528

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

<button type="submit" onClick={() => { this.props.removeTaskFunction(todo) }}>Submit</button>

=> เรียกว่าฟังก์ชั่นลูกศรซึ่งเปิดตัวใน ES6 และจะได้รับการสนับสนุนใน React 0.13.3 หรือสูงกว่า


1
วิธีการทำเช่นนี้ใน coffescript?
vipin8169

14
คุณสามารถหลีกเลี่ยงวงเล็บปีกกาลูกศรฟังก์ชั่นเหล่านี้ได้เช่นกัน ซึ่งฉันเชื่อว่าตรงกับแนวทางปฏิบัติที่ดีที่สุด:onClick={() => this.props.removeTaskFn(todo)}
sospedra

1
คุณช่วยอธิบายเพิ่มเติมอีกหน่อยได้ไหม? ฉันได้รับคนพูดว่ามันไม่ใช่วิธีปฏิบัติที่ดีที่สุด แต่ฉันต้องการที่จะเข้าใจสิ่งที่เกิดขึ้นที่นี่อย่างแน่นอนด้วย () => ฉันเข้าใจว่าฟังก์ชั่นลูกศรคืออะไร แต่ไม่ใช่สิ่งนี้ () และทำไมจึงไม่ดี
wuno

@wuno The () เป็นพารามิเตอร์ของฟังก์ชั่นนิรนามของคุณ มันว่างเปล่าที่นี่เพราะเราไม่ได้ผ่านพารามิเตอร์ใด ๆ ลองจินตนาการว่า () คือ () ของฟังก์ชัน () ตอนนี้เกี่ยวกับสาเหตุว่าทำไมการปฏิบัติที่ดีที่สุดสำหรับการผูกในฟังก์ชั่นการแสดงผล () นั้นไม่ได้เกิดขึ้นกับทุก ๆ การเรนเดอร์เรากำลังรวบรวมฟังก์ชั่นไปยังองค์ประกอบซึ่งอาจมีราคาแพงมาก
jaysonder

@LongNguyen นี่คือสิ่งที่ฉันกำลังมองหา! ขอบคุณมาก
M. Wiśnicki

31

แทนที่จะเรียกใช้ฟังก์ชันผูกค่ากับฟังก์ชัน:

this.props.removeTaskFunction.bind(this, todo)

อ้างอิง MDN: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind


2
IMHO และอื่น ๆ อีกมากมาย คุณควรจะชอบฟังก์ชั่นไร้สัญชาติมากกว่า clasess หรือผูกพันเพราะสิ่งเหล่านี้สามารถนำคุณไปสู่ ดังนั้นแม้จะเป็นคำตอบที่ถูกต้องทั้งคู่ แต่ฉันเชื่อว่าอีกคำหนึ่งมีความหมายมากกว่าอีกคำหนึ่ง
sospedra

1
ไม่แนะนำให้ใช้การเชื่อมโยงโดยตรงในการเรนเดอร์หรือที่อื่นใดในส่วนประกอบ การผูกควรเกิดขึ้นในตัวสร้างเสมอ
Hemadri Dasari

15

ค่าสำหรับonClickแอตทริบิวต์ของคุณควรเป็นฟังก์ชันไม่ใช่การเรียกใช้ฟังก์ชัน

<button type="submit" onClick={function(){removeTaskFunction(todo)}}>Submit</button>

8
อย่าใช้ฟังก์ชั่นที่ไม่ระบุตัวตนในการเรียกอีเวนต์ภายในตัวเรนเดอร์ - มันจะทริกเกอร์เรนเดอร์ตัวอื่น
Splynx

4

สำหรับผู้ที่ไม่ได้ใช้ฟังก์ชั่นลูกศร แต่สิ่งที่ง่ายกว่า ... ฉันพบสิ่งนี้เมื่อเพิ่มวงเล็บหลังจากฟังก์ชั่น signOut ของฉัน ...

แทนที่สิ่งนี้ <a onClick={props.signOut()}>Log Out</a>

ด้วยสิ่งนี้<a onClick={props.signOut}>Log Out</a>... ! 😆


จริงๆแล้วมันไม่ได้ผลสำหรับฉันเลย ฉันผ่านฟังก์ชั่นและไม่เคยเพิ่มวงเล็บและมันยังคงยิงเมื่อแสดงผล ไม่แน่ใจว่าสิ่งนี้มีการเปลี่ยนแปลงตั้งแต่เดือนกุมภาพันธ์ '19 หรือไม่ แต่การกำหนดฟังก์ชันเช่นในคำตอบของ Long Nguyen และ Vishal Bisht ช่วยแก้ไขปัญหา
BitShift

4

JSX ใช้ร่วมกับ ReactJS เนื่องจากคล้ายกับ HTML และให้ความรู้สึกกับโปรแกรมเมอร์ในการใช้ HTML ในขณะที่ transpiles เป็นไฟล์จาวาสคริปต์ในที่สุด

การเขียนสำหรับ for-loop และฟังก์ชั่นการระบุเป็น {this.props.removeTaskFunction (todo)} จะดำเนินการฟังก์ชั่นเมื่อใดก็ตามที่มีการเรียกวง

ในการหยุดพฤติกรรมนี้เราต้องส่งคืนฟังก์ชันกลับไปที่ onClick

ฟังก์ชั่นลูกศรไขมันมีซ่อนผลตอบแทนคำสั่งพร้อมกับคุณสมบัติการผูก ดังนั้นมันจะส่งคืนฟังก์ชันไปยัง OnClick เนื่องจาก Javascript สามารถส่งคืนฟังก์ชันได้เช่นกัน !!!!!

ใช้ -

onClick={() => { this.props.removeTaskFunction(todo) }}

ซึ่งหมายความว่า-

var onClick = function() {
  return this.props.removeTaskFunction(todo);
}.bind(this);

1

JSX จะประเมินผลการแสดงออก JavaScript ในวงเล็บปีกกา

ในกรณีนี้this.props.removeTaskFunction(todo)ถูกเรียกใช้และกำหนดค่าส่งคืนให้onClick

สิ่งที่คุณต้องเตรียมไว้onClickคือฟังก์ชั่น เมื่อต้องการทำเช่นนี้คุณสามารถตัดค่าในฟังก์ชันที่ไม่ระบุชื่อ

export const samepleComponent = ({todoTasks, removeTaskFunction}) => {
    const taskNodes = todoTasks.map(todo => (
                <div>
                    {todo.task}
                    <button type="submit" onClick={() => removeTaskFunction(todo)}>Submit</button>
                </div>
            );
    return (
        <div className="todo-task-list">
            {taskNodes}
        </div>
        );
    }
});

1

ฉันมีปัญหาที่คล้ายกันรหัสของฉันคือ:

function RadioInput(props) {
    return (
    <div className="form-check form-check-inline">
        <input className="form-check-input" type="radio" name="inlineRadioOptions" id={props.id} onClick={props.onClick} value={props.label}></input>
        <label className="form-check-label" htmlFor={props.id}>{props.label}</label>
    </div>
    );
  }
class ScheduleType extends React.Component
{
    renderRadioInput(id,label)
    {
        id = "inlineRadio"+id;
        return(
            <RadioInput
                id = {id}
                label = {label}
                onClick = {this.props.onClick}
            />
        );

    }

มันควรจะอยู่ที่ไหน

onClick = {() => this.props.onClick()}

ในRenderRadioInput

มันแก้ไขปัญหาสำหรับฉัน

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