Javascript 在React中查询状态,并设置状态或更新(如果存在)

Javascript 在React中查询状态,并设置状态或更新(如果存在),javascript,reactjs,Javascript,Reactjs,我正在尝试将交易添加到React中的应用程序中,我希望按年度,然后按月组织这些交易,因此结构如下所示: { "2016" : { "january": { "transaction1": transaction, "transaction2": transaction, "transaction3": transaction }, "february" : { "transaction1": transaction,

我正在尝试将交易添加到React中的应用程序中,我希望按年度,然后按月组织这些交易,因此结构如下所示:

{
  "2016" : {
    "january": {
      "transaction1": transaction,
      "transaction2": transaction,
      "transaction3": transaction
    },
    "february" : {
      "transaction1": transaction,
      "transaction2": transaction,
      "transaction3": transaction
    }
  }
}
我的应用程序中有一个接收事务对象的函数,然后我想将其添加到相关年/月的事务状态中

addTransaction(transaction) {
    const monthNames = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"];
    var year = (new Date()).getFullYear();
    var month = monthNames[(new Date()).getMonth()];
    console.log(
      this.state.transactions != null;
    );
    // check year exists?
    // add if necessary
    // check month exists?
    // add if necessary
  }
我想做的是:

  • 如何查询
    交易
    状态对象中是否存在年份
  • 然后,我需要将其应用于正确的年份和月份(如果确实存在),或者
  • 如果没有,则添加新年和月份
更新: 我已经更新了
addTransaction
,并且正在尝试创建年份(尚未添加月份),然后将该事务添加到该年份,但它没有创建年份,并且我得到了
Uncaught TypeError:无法设置未定义的属性“transaction-1453842528740”

addTransaction(transaction) {
    var timestamp = (new Date()).getTime();
    const monthNames = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"];
    var year = (new Date()).getFullYear();
    var month = monthNames[(new Date()).getMonth()];

    if (year in this.state.transactions) {
      // add to year
    } else {
      this.state.transactions[year]['transaction-' + timestamp] = transaction;
    }

    this.setState({
      transactions: { [year]: this.state.transactions[year] }
    });
  }

提前感谢。

这些是JavaScript问题,我将在下面回答。在ReactJS上下文中,只能更新组件状态中的顶级对象。所以在你的例子中,你不能只更新“一月”;您必须完全替换“2016”

  • 如何查询事务状态对象中是否存在年份
  • 返回true(如果存在)。那么比如说,

    a = {
      "2016" : {
        "january": {
          "transaction1": 1,
          "transaction2": 2,
          "transaction3": 3
        },
        "february" : {
          "transaction1": 4,
          "transaction2": 5,
          "transaction3": 6
        }
      }
    }
    !!a["2016"]
    
    返回真值,以及

    !!a["2015"]
    
    返回false

  • 然后我需要将它应用到正确的年份和月份(如果存在),或者添加新的年份和月份(如果不存在)

  • 只需创建一个新的顶级“2016”对象。这意味着将结构的修改版本传递给setState()。这可能看起来效率低下,但它确实有效。

    这些是JavaScript问题,我将在下面回答。在ReactJS上下文中,只能更新组件状态中的顶级对象。所以在你的例子中,你不能只更新“一月”;您必须完全替换“2016”

  • 如何查询事务状态对象中是否存在年份
  • 返回true(如果存在)。那么比如说,

    a = {
      "2016" : {
        "january": {
          "transaction1": 1,
          "transaction2": 2,
          "transaction3": 3
        },
        "february" : {
          "transaction1": 4,
          "transaction2": 5,
          "transaction3": 6
        }
      }
    }
    !!a["2016"]
    
    返回真值,以及

    !!a["2015"]
    
    返回false

  • 然后我需要将它应用到正确的年份和月份(如果存在),或者添加新的年份和月份(如果不存在)

  • 只需创建一个新的顶级“2016”对象。这意味着将结构的修改版本传递给setState()。这可能看起来效率低下,但它确实有效。

    如果您喜欢改变对象,您可以这样做:

    const transactions = this.state.transactions;
    // get or create the year object
    const yearObject = transactions[year] || (transactions[year] = {});
    // get or create the month object
    const monthObject = yearObject[month] || (yearObject[month] = {});
    // add the transaction
    const transactionId = `transaction-${timestamp}`;
    monthObject[transactionId] = transaction;
    this.setState({ transactions });
    
    这是您以不变的方式实现的方式(这将使您的组件变得纯粹:

    const transactions = this.state.transactions;
    // get or create the year object
    const yearObject = transactions[year] || {};
    // get or create the month object
    const monthObject = yearObject[month] || {};
    // add the transaction
    const transactionId = `transaction-${timestamp}`;
    
    const newTransactions = {
        // copy the old object
        ...transactions,
        // assign a copy of the year object
        [year]: {
            // copy the old year object
            ...yearObject,
            // assign a copy of the month object
            [month]: {
                // copy the old month object
                ...monthObject,
                // add the new transaction
                [transactionId]: transaction
            }
        }
    };
    
    // assign our new object
    this.setState({ transactions: newTransactions });
    

    如果你喜欢改变你的对象,你可以这样做:

    const transactions = this.state.transactions;
    // get or create the year object
    const yearObject = transactions[year] || (transactions[year] = {});
    // get or create the month object
    const monthObject = yearObject[month] || (yearObject[month] = {});
    // add the transaction
    const transactionId = `transaction-${timestamp}`;
    monthObject[transactionId] = transaction;
    this.setState({ transactions });
    
    这是您以不变的方式实现的方式(这将使您的组件变得纯粹:

    const transactions = this.state.transactions;
    // get or create the year object
    const yearObject = transactions[year] || {};
    // get or create the month object
    const monthObject = yearObject[month] || {};
    // add the transaction
    const transactionId = `transaction-${timestamp}`;
    
    const newTransactions = {
        // copy the old object
        ...transactions,
        // assign a copy of the year object
        [year]: {
            // copy the old year object
            ...yearObject,
            // assign a copy of the month object
            [month]: {
                // copy the old month object
                ...monthObject,
                // add the new transaction
                [transactionId]: transaction
            }
        }
    };
    
    // assign our new object
    this.setState({ transactions: newTransactions });
    

    在操作符中有一个
    ,用于检查键的存在。
    !!
    看起来很混乱,可能有误报。非常感谢John,肯定能做到这一点,但是我得到了
    未捕获的类型错误:无法用更新的代码设置未定义的
    的属性“transaction-1453842661026”。(已使用更新的代码编辑了我的原始帖子。我使用的代码没有设置年份和事务。感谢您的帮助。您似乎试图直接设置this.state.transactions,这在ReactJS中不起作用。您必须使用此.setState({transactions:…});为事务提供一个完整的对象。该对象是this.state.transactions的副本,可以根据需要进行修改。我刚刚在另一个建议的解决方案中看到了@Brandon的“不可变”版本;我建议这样做。
    操作符中有一个
    ,用于检查键的存在。
    !!
    看起来很混乱,可能有误报。谢谢很多John,肯定达到了这一点,但是我得到了
    未捕获的TypeError:无法使用更新的代码设置未定义的属性“transaction-1453842661026”。(已使用更新的代码编辑了我的原始帖子。我使用的代码没有设置年份和事务。感谢您的帮助。您似乎试图直接设置this.state.transactions,这在ReactJS中不起作用。您必须使用此.setState({transactions:…});为事务提供一个完整的对象。该对象是this.state.transactions的副本,可以根据需要进行修改。我刚刚在另一个建议的解决方案中看到了@Brandon的“不可变”版本;我建议这样做。您只需将
    setState
    行移到
    else
    块中即可;您不应该操纵state direcThy!您只需将
    setState
    行移动到
    else
    块中即可;您不应该直接操纵状态!太好了,谢谢您Brandon:)我可以问一下,关于复制现有事务/年/月对象的技术,使用…事务等…这叫什么?React文档中是否有关于这一点的内容,以便我可以阅读?再次感谢。这是JavaScript ES7语法。我相信它被称为object spread运算符。根据您的代码示例,看起来您正在使用Babel,因此,只要您启用了它,并且您可以在他们的网站上阅读有关语法的信息,它就应该可以工作。谢谢您-是的,使用Babel。完美,谢谢您Brandon:)我可以问一下,关于复制现有事务/年/月对象的技术,使用…事务等…这叫什么?React文档中是否有关于这一点的内容,以便我可以阅读?再次感谢。这是JavaScript ES7语法。我相信它被称为object spread运算符。根据您的代码示例,看起来您正在使用Babel,因此,只要您启用了它,并且您可以在他们的网站上阅读有关语法的内容,它就应该可以工作。谢谢您——是的,使用Babel。