简体   繁体   中英

How to handle onClick event inside a conditional component

I'm trying to add the onClick event on the data I selected from the AsyncTypeahead. I'm passing the callback function to the Problem that renders only if I've selected an item. But after selecting an item it directly calling the callback function that I passed to Problem component

This is main Component

constructor(props) {
    super(props);

    this.state = {
        plateform: '',
        selected: [],
        isLoading: false,
        options: []
    };
    this.handleInputChange = this.handleInputChange.bind(this);
    this.saveTodo = this.saveTodo.bind(this);
}

async handleInputChange(event) {
    const target = event.target;
    const value = target.value;
    const name = target.name;

    await this.setState({
      [name]: value
    });
}

saveTodo(problemID) {
    axios.post(`${API}/todos`,
    {
        problemID: problemID
    },
    {
        headers: {
            Accept: "application/json",
            'Content-Type': 'application/json',
            'Authorization': 'Bearer ' + this.props.auth.token
        }
    })
    .then(() => alert("Problem saved to todo list"))
    .catch((err) => {
        if (err.response) {
            alert(err.response.data);
        }
        else {
            alert("Sorry! A server error occurred. Try to save this problem later!");
        }
    });
}


render() {

    return (
        <>
            <TrainLayout auth={this.props.auth} deauthenticate={this.props.deauthenticate} title={title} description={description} >
                <div className="container">
                    <div className="row justify-content-center">
                        <div className="offset-md-3 col-md-7 offset-2">
                            <br />
                            <div className="form-group row">
                                <label htmlFor="oj" className="col-4 col-form-label col-form-label-sm">Online Judge</label>
                                <div className="col-8 col-md-5">
                                    <select id="oj" type="select" className="form-control form-control-sm" name="plateform" onChange={this.handleInputChange} value={this.state.plateform}>
                                        <option value="all">All Online Judges</option>
                                        <option value="xxx">XXX</option>
                                        <option value="yyy">YYY</option>
                                        <option value="zzz">ZZZ</option>
                                    </select>
                                </div>
                            </div>
                            <div className="form-group row">
                                <label htmlFor="pname" className="col-4 col-form-label col-form-label-sm">Problem Name</label>
                                <div className="col-8 col-md-5">
                                    <AsyncTypeahead
                                        isLoading={this.state.isLoading}
                                        allowNew={false}
                                        multiple={false}
                                        id="pname"
                                        labelKey={option => `${option.name} (${option.plateform})`}
                                        minLength={2}
                                        onChange={selected => this.setState({ selected })}
                                        placeholder="Search for a problem"
                                        onSearch={query => {
                                            this.setState({isLoading: true});
                                            axios.get(`${API}/problems/${query}`,
                                            {
                                                params: {
                                                    plateform: this.state.plateform
                                                },
                                                headers: {
                                                    Accept: "application/json",
                                                    'Content-Type': 'application/json',
                                                    'Authorization': 'Bearer ' + this.props.auth.token
                                                }
                                            })
                                            .then((response) => { /* eslint-disable-line camelcase */
                                                const options = response.data.map((problem) => ({
                                                    _id: problem._id,
                                                    problemID: problem.problemID,
                                                    name: problem.name,
                                                    plateform: problem.plateform,
                                                    link: problem.link,
                                                    difficulty: problem.difficulty
                                                }));
                                                console.log("DATA: ", options);
                                                this.setState({
                                                    isLoading: false,
                                                    options: options,
                                                });
                                            });
                                        }}
                                        options={this.state.options} />
                                </div>
                            </div>

                        </div>
                    </div>
                </div>
                <br /><br />
                <div className="container">
                    <div className="row justify-content-center">
                        {!!this.state.selected &&
                        (
                        <Problem saveTodo={this.saveTodo} problem={this.state.selected[0]} />)
                        }
                    </div>
                </div>
            </TrainLayout>
        </>
    );
}

I expect the Onclick event to be called when I click on the font-awesome icon but it fires when I select an item from AsyncTypeahead

    const Problem = ({problem, saveTodo}) => {
if (!problem) {
    return (
        <></>
    );
}
return (
    <>
        <table className="table table-sm table-bordered table-striped table-responsive-sm table-hover">
            <thead>
                <tr className="text-center">
                    <th>Name</th>
                    <th>Online Judge</th>
                    <th>Difficulty</th>
                    <th>Add Todo</th>
                    <th>Solve</th>
                </tr>
            </thead>
            <tbody>
                <tr className="text-center">
                    <td> {problem.name} </td>
                    <td> {problem.plateform} </td>
                    <td> {problem.difficulty} </td>
                    <td> <a onClick={saveTodo(problem.problemID)}><FontAwesomeIcon icon="save" /></a> </td>
                    <td> <a href={`${problem.link}`} target="_blank"> Solve </a> </td>
                </tr>
            </tbody>
        </table>
        <br />
        <div className="row justify-content-center">
            <p>Note: Difficulty is not 100% accurate</p>
        </div>
    </>
);}

You should be passing a function as the event handler. In your example you are calling the function immediately. Try the following.

<td> <a onClick={() => saveTodo(problem.problemID)}><FontAwesomeIcon icon="save" /></a> </td>

See Handling Events - React for more info.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM