简体   繁体   English

在 React Context 中,如何在 state 函数中使用 state 变量?

[英]In React Context, how can I use state variables in state functions?

I have a React Context which looks like this:我有一个看起来像这样的 React 上下文:

import React, { Component } from 'react'

const AlertsContext = React.createContext({
  categoryList: [],
  setCategoryList: () => {}
})

export class AlertsProvider extends Component {

  state = {
    categoryList: [],
    setCategoryList: categoryString => (
      this.categoryList.includes(categoryString)
        ? this.setState({ categoryList: this.categoryList.filter(value => value !== categoryString) })
        : this.setState({ categoryList: this.categoryList.concat([categoryString]) })
    )
  }

  render() {
    const { children } = this.props
    const {categoryList, setCategoryList } = this.state

    return (
      <AlertsContext.Provider value={{categoryList, setCategoryList}}>
        {children}
      </AlertsContext.Provider>
    )
  }
}

export const AlertsConsumer = AlertsContext.Consumer

So, categoryList is an array of strings, each representing a category.因此,categoryList 是一个字符串数组,每个字符串代表一个类别。 setCategoryList should take a string; setCategoryList 应该是一个字符串; if that string is already in the array, it removes it, and if it's not in the array it adds it.如果该字符串已经在数组中,则将其删除,如果不在数组中,则将其添加。

In one of my components the user can select categories from a list of checkboxes.在我的一个组件中,用户可以从复选框列表中选择 select 类别。 When a checkbox is clicked, the AlertsContext setCategoryList should be called with the value of the clicked box:单击复选框时,应使用单击框的值调用 AlertsContext setCategoryList:

import React, { Component } from 'react'
import { AlertsConsumer } from '../../../context/alerts-context'


    class AlertFilters extends Component {
    
      constructor(props) {
        super(props)
        this.state = {
          categories: props.categories
        }
      }
    
      render() {
        const { categories } = this.state
    
        return (
          <AlertsConsumer>
            {({ categoryList, setCategoryList }) => (
              <>
                {
                categories.map(category => (
                  return (
                    <div key={category.id}>
                      <Checkbox id={category.id} value={category.value} onChange={e => setCategoryList(e.target.value)} checked={categoryList.includes(category.value)} />
                      <label htmlFor={category.id}>{category.value}</label>
                    </div>
                  )
                ))
                }
              </>
            )}
          </AlertsConsumer>
        )
      }
    }
    
    export default AlertFilters

This compiles ok, but when I run it and click a checkbox I get the following error:这可以编译,但是当我运行它并单击一个复选框时,我收到以下错误:

alerts-context.jsx:77 Uncaught TypeError: Cannot read property 'includes' of undefined

This is in the line:这是行中的:

  this.categoryList.includes(categoryString)

in the Context Provider, suggesting that "this.categoryList" is undefined at this point.在 Context Provider 中,提示“this.categoryList”此时未定义。

I tried changing it to我尝试将其更改为

this.state.categoryList.includes(categoryString)

but it said I had to use state destructuring, so I changed to:但它说我必须使用 state 解构,所以我改为:

setCategoryList: (categoryString) => {
      const { categoryList } = this.state
      categoryList.includes(categoryString)
        ? this.setState({ categoryList: categoryList.filter(value => value !== categoryString) })
        : this.setState({ categoryList: categoryList.concat([categoryString]) })
    }

which highlighted the ternary operator and gave the following lint error:它突出显示了三元运算符并给出了以下 lint 错误:

Expected an assignment or function call and instead saw an expression.

What am I doing wrong?我究竟做错了什么?

Use if/else syntax to update the state.使用if/else语法更新 state。

setCategoryList: categoryString => {
  const { categoryList } = this.state;
  if (categoryList.includes(categoryString)) {
    this.setState({
      categoryList: categoryList.filter(value => value !== categoryString)
    });
  } else {
    this.setState({ categoryList: categoryList.concat([categoryString]) });
  }
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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