Bereaksi fungsi onClick mengaktifkan render


212

Saya meneruskan 2 nilai ke komponen anak:

  1. Daftar objek untuk ditampilkan
  2. hapus fungsi.

Saya menggunakan fungsi .map () untuk menampilkan daftar objek saya (seperti pada contoh yang diberikan pada halaman tutorial bereaksi), tetapi tombol pada komponen tersebut mengaktifkan onClickfungsi, pada render (seharusnya tidak menyala pada waktu render). Kode saya terlihat seperti ini:

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>
        );
    }
});

Pertanyaan saya adalah: mengapa onClickfungsi menyala saat render dan bagaimana membuatnya tidak?

Jawaban:


528

Karena Anda memanggil fungsi itu alih-alih meneruskan fungsi ke onClick, ubah baris itu ke ini:

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

=> disebut Arrow Function, yang diperkenalkan pada ES6, dan akan didukung pada React 0.13.3 atau lebih tinggi.


1
bagaimana melakukan ini dalam coffescript?
vipin8169

14
Anda dapat menghindari kurung kurawal fungsi panah ini juga. Yang saya percaya cocok dengan praktik terbaik:onClick={() => this.props.removeTaskFn(todo)}
sospedra

1
Tolong jelaskan ini sedikit lagi. Saya mendapatkan bahwa orang-orang terus mengatakan itu bukan praktik terbaik tetapi saya ingin memahami apa yang sebenarnya terjadi di sini dengan () => Saya mengerti apa fungsi panah tetapi bukan apa ini () dan mengapa ini buruk?
wuno

@wuno The () adalah parameter fungsi anonim Anda. Di sini kosong karena kami tidak memberikan parameter apa pun. Bayangkan bahwa () adalah () dari fungsi (). Sekarang mengenai mengapa itu bukan praktik terbaik untuk mengikat dalam fungsi render () karena pada setiap render, kami mengubah fungsi ke komponen, yang bisa sangat mahal.
jaysonder

@ LongNguyen Inilah yang saya cari! terima kasih banyak
M. Wiśnicki

31

Alih-alih memanggil fungsi, ikat nilai ke fungsi:

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

MDN ref: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind


2
IMHO dan banyak lainnya. Anda harus memilih fungsi stateless daripada clasess atau binding karena mereka dapat membawa Anda ke efek samping yang tidak diinginkan. Oleh karena itu, walaupun kedua jawaban itu benar, saya percaya yang satu lebih cocok daripada yang lain.
sospedra

1
Pengikatan langsung dalam render atau di mana pun dalam komponen tidak direkomendasikan. Mengikat harus selalu terjadi dalam konstruktor
Hemadri Dasari

15

Nilai untuk onClickatribut Anda harus berupa fungsi, bukan panggilan fungsi.

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

8
Jangan gunakan fungsi anonim pada panggilan acara di dalam render - itu akan memicu render lain
Splynx

4

Bagi mereka yang tidak menggunakan fungsi panah tetapi sesuatu yang lebih sederhana ... Saya menemukan ini ketika menambahkan tanda kurung setelah fungsi signOut saya ...

ganti ini <a onClick={props.signOut()}>Log Out</a>

dengan ini <a onClick={props.signOut}>Log Out</a>...! 😆


Sebenarnya itu tidak bekerja untuk saya sama sekali. Saya mewariskan fungsi dan tidak pernah menambahkan tanda kurung dan itu masih diaktifkan. Tidak yakin apakah ini telah berubah sejak Februari '19 tetapi menetapkan fungsi seperti dalam jawaban Long Nguyen dan Vishal Bisht memperbaiki masalah ini.
BitShift

4

JSX digunakan dengan ReactJS karena sangat mirip dengan HTML dan memberikan programmer merasa menggunakan HTML sedangkan pada akhirnya transpiles ke file javascript.

Menulis fungsi for-loop dan menetapkan sebagai {this.props.removeTaskFunction (todo)} akan menjalankan fungsi-fungsi setiap kali loop dipicu.

Untuk menghentikan perilaku ini, kita perlu mengembalikan fungsi ke onClick.

Fungsi panah gemuk memiliki pernyataan pengembalian tersembunyi bersama dengan properti bind . Jadi itu mengembalikan fungsi ke OnClick karena Javascript dapat mengembalikan fungsi juga !!!!!

Gunakan -

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

yang berarti-

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

1

JSX akan mengevaluasi ekspresi JavaScript dalam kurung kurawal

Dalam hal ini, this.props.removeTaskFunction(todo)dipanggil dan nilai kembali ditugaskan untukonClick

Apa yang harus Anda sediakan onClickadalah fungsi. Untuk melakukan ini, Anda bisa membungkus nilai dalam fungsi anonim.

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

Saya memiliki masalah serupa, kode saya adalah:

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}
            />
        );

    }

Di mana seharusnya

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

dalam RenderRadioInput

Itu memperbaiki masalah bagi saya.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.