Phản ứng chức năng onClick kích hoạt khi kết xuất


209

Tôi truyền 2 giá trị cho một thành phần con:

  1. Danh sách các đối tượng cần hiển thị
  2. xóa chức năng.

Tôi sử dụng hàm .map () để hiển thị danh sách các đối tượng của mình (như trong ví dụ được đưa ra trong trang hướng dẫn phản ứng), nhưng nút trong thành phần đó kích onClickhoạt chức năng, khi kết xuất (không nên kích hoạt thời gian kết xuất). Mã của tôi trông như thế này:

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

Câu hỏi của tôi là: tại sao onClickchức năng kích hoạt kết xuất và làm thế nào để nó không hoạt động?

Câu trả lời:


526

Vì bạn đang gọi hàm đó thay vì chuyển hàm cho onClick, hãy thay đổi dòng đó thành:

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

=> được gọi là Chức năng Mũi tên, được giới thiệu trong ES6 và sẽ được hỗ trợ trên React 0.13.3 trở lên.


1
Làm thế nào để làm điều này trong coffescript?
vipin8169

14
Bạn cũng có thể tránh các mũi tên hàm niềng răng. Mà tôi tin rằng phù hợp với các thực tiễn tốt nhất:onClick={() => this.props.removeTaskFn(todo)}
sospedra

1
Bạn vui lòng giải thích điều này nhiều hơn một chút? Tôi hiểu rằng mọi người cứ nói nó không phải là cách thực hành tốt nhất nhưng tôi muốn hiểu chính xác những gì đang xảy ra ở đây với () => Tôi hiểu hàm mũi tên là gì nhưng không phải là cái gì () và tại sao điều này lại xấu?
wuno

@wuno () là các tham số của hàm ẩn danh của bạn. Nó trống ở đây vì chúng tôi không chuyển bất kỳ tham số nào. Hãy tưởng tượng rằng () là () của hàm (). Bây giờ về lý do tại sao nó không phải là cách thực hành tốt nhất để liên kết trong hàm render () là bởi vì trên mỗi kết xuất, chúng tôi đang chỉnh lại hàm cho thành phần, điều này có thể rất tốn kém.
jaysonder

@LongNguyen Đây là thứ tôi đang tìm kiếm! cảm ơn rất nhiều
M. Wiśnicki

31

Thay vì gọi hàm, liên kết giá trị với hàm:

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

Tham chiếu MDN: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind


2
IMHO và nhiều người khác. Bạn nên ưu tiên các chức năng không trạng thái hơn clasess hoặc ràng buộc bởi vì chúng có thể dẫn bạn đến các tác dụng phụ không mong muốn. Do đó, ngay cả khi cả hai câu trả lời đều đúng, tôi tin rằng cái này phù hợp hơn cái kia.
sospedra

1
Liên kết trực tiếp trong kết xuất hoặc bất cứ nơi nào khác trong thành phần không được khuyến nghị. Liên kết nên luôn luôn xảy ra trong nhà xây dựng
Hemadri Dasari

15

Giá trị cho onClickthuộc tính của bạn phải là một hàm, không phải là một hàm gọi.

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

8
Không sử dụng các chức năng ẩn danh cho các cuộc gọi sự kiện bên trong kết xuất - nó sẽ kích hoạt kết xuất khác
Splynx

4

Đối với những người không sử dụng các hàm mũi tên nhưng đơn giản hơn ... Tôi đã gặp phải điều này khi thêm dấu ngoặc đơn sau hàm SignOut của mình ...

thay thế cái này <a onClick={props.signOut()}>Log Out</a>

với điều này <a onClick={props.signOut}>Log Out</a>...! 😆


Trên thực tế điều đó không làm việc cho tôi cả. Tôi đã truyền lại hàm và không bao giờ thêm dấu ngoặc đơn và nó vẫn được kích hoạt khi kết xuất. Không chắc điều này có thay đổi kể từ ngày 19 tháng 2 hay không nhưng việc gán một chức năng như trong câu trả lời của Long Nguyễn và Vishal Bisht đã khắc phục vấn đề.
BitShift

4

JSX được sử dụng với ReactJS vì nó rất giống với HTML và nó mang lại cho các lập trình viên cảm giác sử dụng HTML trong khi cuối cùng nó chuyển sang một tệp javascript.

Viết hàm for-loop và chỉ định là {this.props.removeTaskFunction (todo)} sẽ thực thi các chức năng bất cứ khi nào vòng lặp được kích hoạt.

Để dừng hành vi này, chúng tôi cần trả lại chức năng cho onClick.

Hàm mũi tên chất béo có một tuyên bố trả lại ẩn cùng với thuộc tính liên kết . Do đó, nó trả lại chức năng cho OnClick vì Javascript cũng có thể trả về các chức năng !!!!!

Sử dụng -

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

nghĩa là-

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

1

JSX sẽ đánh giá các biểu thức JavaScript trong dấu ngoặc nhọn

Trong trường hợp này, this.props.removeTaskFunction(todo)được gọi và giá trị trả về được gán choonClick

Những gì bạn phải cung cấp cho onClicklà một chức năng. Để làm điều này, bạn có thể bọc giá trị trong một hàm ẩn danh.

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

Tôi đã có vấn đề tương tự, mã của tôi là:

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

    }

Nó nên ở đâu

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

trong RenderRadioInput

Nó đã khắc phục vấn đề cho tôi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.