【问题标题】:How can I optimize my code in a way where only one method is required (if possible)?如何以只需要一种方法的方式优化我的代码(如果可能)?
【发布时间】:2018-08-13 12:56:09
【问题描述】:

我正在尝试以一种不需要 3 种不同方法(或者我决定在未来包含多少种方法)的方式优化我的代码,以便在数据库中安全地存储用户选择的食物类型用户单击相应的按钮。

我尝试了许多不同的方法,但我的代码不断出错,最终我只能自寻烦恼。我觉得优化效率很低,因为每种食物类型都不同,这意味着我们需要不同的方法来将不同的食物存储在数据库中。

旁注:就用户选择而言,该模式运行良好,在单击所需的食物类型时会一一出现。我希望以某种方式优化我的代码,如果用户决定不再想要那种特定的食物,我可以添加删除功能(但我可以稍后处理)。

(我是react的菜鸟,请原谅我=D)

那么有没有可能让我的代码比现在更干净?

这是我的代码:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import Modal from 'react-modal';

import Aux from '../../../../hoc/Aux';
import FoodButton from '../FoodButtons/FoodButton';
import CheckoutButton from '../CheckoutButton/CheckoutButton';
import axios from '../../../../axios-foodChosen';

import { CLOSE_MODAL, OPEN_MODAL } from "../../../../store/action/NoNameAction";

class TacoTypes extends Component {
    state = {
        items: {
            cTacoClicked: false,
            cTaco: '',

            bTacoClicked: false,
            bTaco: '',

            cBurritoSelected: false,
            cBurrito: ''
        }
    }

    componentWillMount() {
        // for modal
        Modal.setAppElement('body');
    }

    chickenTaco() {
        // modal
        const cTacoSelected = "Chicken Taco";
        this.setState({cTacClicked: true, cTaco: cTacoSelected});

        // firebase
        let name = "Chicken Taco";
        axios.post('./chosen.json', { name })
            .then(response => {
                console.log("chicken taco check firebase");
            }).catch(error => {
            console.log(error);
        })
    }

    beefTaco() {
        // modal
        const bTacoSelected = "Beef Taco";
        this.setState({bTacoClicked: true, bTaco: bTacoSelected});

        // firebase
        let name = "Beef Taco";
        axios.post('./chosen.json', { name })
            .then(response => {
                console.log("beef taco check firebase");
            }).catch(error => {
            console.log(error);
        })

    }

    chickenBurrito() {
        // modal
        const cBurritoSelected = "Chicken Burrito";
        this.setState({cBurritoSelected: true, cBurrito: cBurritoSelected });

        // firebase
        let name = "Chicken Burrito";
        axios.post('./chosen.json', { name })
            .then(response => {
                console.log("chicken burrito check firebase");
            }).catch(error => {
            console.log(error);
        })

    }

    render() {
        return (
            <Aux>
                <FoodButton clicked={() => this.chickenTaco()} label={"Chicken Taco"}/>
                <FoodButton clicked={() => this.beefTaco()} label={"Beef Taco"}/>
                <FoodButton clicked={() => this.chickenBurrito()} label={"Chicken Burrito"}/>

                <CheckoutButton clicked={() => this.props.openModalRedux()}/>

                <Modal isOpen={this.props.isOpen}>
                    <p>
                        {Object.keys(this.state.items).map(key => (
                            <p key={key}>{this.state[key]}</p>
                        ))}
                    </p>
                    <button onClick={() => this.props.closeModalRedux()}>Close</button>
                </Modal>
            </Aux>
        );
    }
}

const mapStateToProps = state => {
    return {
        // props for modal
        isOpen: state.global.isModalOpen,
    }
};

const mapDispatchToProps = dispatch => {
    return {
        // Modal handlers
        openModalRedux: () => dispatch({type: OPEN_MODAL}),
        closeModalRedux: () => dispatch({type: CLOSE_MODAL})
    }
};

export default connect(mapStateToProps, mapDispatchToProps)(TacoTypes);

【问题讨论】:

  • 每种 taco 类型的代码之间的唯一区别是 taco 的名称。因此,只需在单一食物函数上创建并将 taco 名称作为参数插入即可。然后将所有 taco 存储在一个数组中,而不是为每个单独的 taco 类型存储一个属性。用户购买什么并不重要,您应该能够将 tacos 更改为水果,而无需更改与插入数据库相关的任何内容。
  • 我恰好是评论这段代码的清洁度的人,我支持my suggestions。不过,这种帖子可能更适合另一个 Stack Exchange 网站 Code Review SE。
  • @NonameSL 是的,我记得。我试过你的建议(谢谢!)。它起作用了,但是,模态上一次只出现一种食物类型(在模态中不允许超过一种食物类型)。我希望用户点击的所有按钮都出现在模式中。
  • @sp92 我明白你的意思了。您可以修改它,而不是 selectedItem 您将拥有 selectedItems ,这将是您从中推和拉的数组。我现在将发布带有完整代码的答案。
  • @NonameSL 好的,谢谢。

标签: javascript reactjs debugging optimization


【解决方案1】:

我已将其范围缩小到以下主要问题:

  • 您正在声明您所在州的常量。这是不好的做法,没有理由这样做。状态应该包括变化的动态变量。您不应在其中包含诸如食物名称之类的常量。
  • 您的代码不是DRY(D不是R重复Y我们自己)。您应该找到泛化代码的方法。例如,如果您的三个方法执行相同的操作,但使用不同的食物,您可以将要对其执行操作的食物作为变量传递,并使用一个方法执行相同的操作。

这是您的代码在应用这些原则时的样子(为了方便起见,我没有包含所有您的代码):

//Imports, blah blah blah
class TacoTypes extends Component {
    constructor(props) {
        //It's common practice to declare your state in the constructor.

        this.state = {
            selectedItems: [],
        };

        //Constant item names
        this.items = {
            chickenTaco: 'Chicken Taco',
            beefTaco: 'Beef Taco',
            chickenBurrito: 'Chicken Burrito',
        };
    }

    componentWillMount() {
        // for modal
        Modal.setAppElement('body');
    }
    selectFood(food) {
        this.setState(state => {
            //Dynamically setting state to avoid race conditions
            let selected = state.selectedItems;
            if(!selected.includes(food)) selected.push(food);
            return {selectedItems: selected};
        });

        //Do whatever with firebase here...
        //You can get the name using this.items[food]
    }

    render() {
        return (
            <Aux>
                {Object.keys(this.items).map(key => (
                    //Keeping our code DRY, we dynamically create the food buttons.
                    //React will throw a warning if we don't supply a unique key prop when dynamically creating variables using loops.
                    <FoodButton key={key} clicked={() => this.selectFood(key)} label={this.items[key]} />
                ))}

                <CheckoutButton clicked={() => this.props.openModalRedux()}/>

                <Modal isOpen={this.props.isOpen}>
                    <p>
                        {
                            //According to your comments I assume you want to display the items
                            //selected only, unlike what you originally coded:
                            this.state.selectedItems.map(key => (
                                <p key={key}>{this.items[key]}</p>
                            ))
                        ))}
                    </p>
                    <button onClick={() => this.props.closeModalRedux()}>Close</button>
                </Modal>
            </Aux>
        );
    }
}
//Include the rest of your code here

请注意代码中的 cmets,因为他们解释了我的行为,这将帮助您了解我正在做的事情背后的基本原理。

【讨论】:

  • 从来没有在一篇文章中学到这么多,非常感谢。如果可以的话,我会给你一个拥抱。
  • 对 SO 的拥抱相当于一个支持;)很高兴你学到了更多!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-16
  • 2013-12-30
  • 2016-03-05
  • 2017-06-26
相关资源
最近更新 更多