简体   繁体   English

如何在反应中显示动态状态

[英]How can I display dynamic state in react

I create a state dynamically, but I need use this state in my render.我动态创建一个state ,但我需要在我的渲染中使用这个state

See my issue:看我的问题:

handleChange = (name, checked) => {
  this.setState({
    [name]: checked,
  })
}

So, in my render how can I display my [name] state?那么,在我的render如何显示我的[name]状态? (I don't know his name, since it's dynamic) (我不知道他的名字,因为它是动态的)

render(){

  console.log(this.state....?)

  return(
    <p>Hello</p>
  )
}

My function handleChange is called when I checked my checbkox.当我检查我的 checbkox 时,我的函数handleChange被调用。 So, if I have 5, 10, 20 checkboxes how can I display my [name] state?那么,如果我有 5、10、20 个复选框,我该如何显示我的[name]状态?

----> UPDATE - FULL CODE <---- ----> 更新 - 完整代码 <----
I'm using a hover propriety to display my checkbox:我正在使用悬停属性来显示我的复选框:

CSS using material ui: CSS 使用材质 ui:

  hideCheckbox: {
    display: 'none',
  },
  showCheckbox: {
    display: 'initial',
  },

My main class:我的主要课程:

export class Item extends Component {

state = { 
  isHovering: true,
  checkboxChecked: false,
}

handleGetCardSelected = (id, checked) => { 
 //Here I set isHovering to display my checkbox
 //checkboxChecked is a control variable to always display the checkbox if it's checked

  if(checked){
    this.setState({
      isHovering: !this.state.isHovering,
      checkboxChecked: true,
    })

  } else {
    this.setState({
      checkboxChecked: false,
    })
  }
}

handleMouseHover = () => {
  if(!this.state.checkboxChecked){
    this.setState(this.toggleHoverState);
  }
}

toggleHoverState = (state) => {
  return {
    isHovering: !state.isHovering,
  };
}
return(
 <div 
   onMouseEnter={this.handleMouseHover} 
   onMouseLeave={this.handleMouseHover}
  >
   <div className={`
     ${this.state.isHovering && classes.hideCheckbox }
     ${this.state.checkboxChecked && classes.showCheckbox}
    `}>
      <CheckBoxCard handleGetCardSelected={this.handleGetCardSelected}/>
    </div>
  </div>

 <div 
   onMouseEnter={this.handleMouseHover} 
   onMouseLeave={this.handleMouseHover}
  >
   <div className={`
     ${this.state.isHovering && classes.hideCheckbox }
     ${this.state.checkboxChecked && classes.showCheckbox}
    `}>
      <CheckBoxCard handleGetCardSelected={this.handleGetCardSelected}/>
    </div>
  </div>

 <div 
   onMouseEnter={this.handleMouseHover} 
   onMouseLeave={this.handleMouseHover}
  >
   <div className={`
     ${this.state.isHovering && classes.hideCheckbox }
     ${this.state.checkboxChecked && classes.showCheckbox}
    `}>
      <CheckBoxCard handleGetCardSelected={this.handleGetCardSelected}/>
    </div>
  </div>
 )
 }

My CheckboxCard:我的复选框卡:

import React from 'react';
import { makeStyles, withStyles } from '@material-ui/core/styles';
import { Checkbox } from '@material-ui/core';
const GreenCheckbox = withStyles({
  root: {
    color: '#43a04754',
    '&$checked': {
      color: '#43a047',
    },
    '&:hover': {
      color: '#43a047',
      backgroundColor: 'initial',
    },
  },
  checked: {},
})(props => <Checkbox color="default" {...props} />);

export default function CheckBoxCard(props){
  const [state, setState] = React.useState({
    idItem: false,
  });

  const handleCheckbox = name => event => {
    setState({ ...state, [name]: event.target.checked });

    let id = name
    let checked = event.target.checked
    props.handleGetCardSelected(id, checked)
  };

  return(
    <GreenCheckbox
      checked={state.idItem}
      onChange={handleCheckbox('idItem')}
      value="idItem"
      inputProps={{
        'aria-label': 'primary checkbox',
      }}
    />
  );
}

By default, my checkbox is hidden because my state isHovering is true, so the css variable hideCheckbox ('display: none') is set.默认情况下,我的复选框是隐藏的,因为我的state isHovering为真,因此设置了 css 变量 hideCheckbox ('display: none')。

If I hover the element, is called handleMouseHover and the checkbox is displayed!如果我悬停该元素,则称为handleMouseHover并显示复选框!

If I checked my checkbox, is set checkboxChecked for true and now I'm always displaying my checkbox!如果我选中了我的复选框,则将checkboxChecked设置为true ,现在我总是显示我的复选框! But, if I've two or more elements, all checkbox is displayed, because checkboxChecked is an unique element!但是,如果我有两个或更多元素,则会显示所有复选框,因为checkboxChecked是一个唯一元素!

So, my checkboxChecked must be dynamic and per item!所以,我的checkboxChecked必须是动态的并且是每个项目! In this way, if is checked , only this checkbox will be displayed.这样,如果被checked ,则只显示此复选框。 The others no!其他没有!

For first element:对于第一个元素:
${this.state.checkboxCheckedITEM1 && classes.showCheckbox}

For second element:对于第二个元素:
${this.state.checkboxCheckedITEM2 && classes.showCheckbox}

For second element:对于第二个元素:
${this.state.checkboxCheckedITEM3 && classes.showCheckbox}

I update my code in sandbox: https://codesandbox.io/embed/material-demo-16t91?fontsize=14我在沙箱中更新我的代码: https : //codesandbox.io/embed/material-demo-16t91? fontsize =14

How can I do that?我怎样才能做到这一点?

So, if I have 5, 10, 20 checkboxes how can I display my [name] state?那么,如果我有 5、10、20 个复选框,我该如何显示我的 [name] 状态?

I think the smart way to do this is to nest components.我认为这样做的明智方法是嵌套组件。 Have an abstract parent component, that only renders the child component once the name is available.有一个抽象的父组件,只有在名称可用时才会呈现子组件。 By using this pattern your problem can be solved.通过使用这种模式,您的问题可以得到解决。

Check out this helpful article 看看这篇有用的文章

您可以过滤对象以仅获取已检查的名称。

Object.keys(this.state).filter(name => this.state[name]);

If you have a finite list of checkbox component如果您有有限的checkbox组件列表

render() {
  return (
    <div>
      <Checkbox
        handleChange={() => this.handleChange('abc', !this.state[abc])}
        className={this.state['abc'] ? 'checked-class' : '' }
      />
    </div>
  )
}

In another situation whereby you render a list of dynamic checkbox.在另一种情况下,您呈现动态复选框列表。

componentDidMount() {
  //Calling API to return dynamic list of checkboxes, and dump them into a state
  this.setState({ listOfCheckboxes });
}

Then in your render method, you will be using .map function然后在您的render方法中,您将使用.map函数

render() {
  return (
    <div>
    {
      this.state.listOfCheckboxes.map(x => (
        <Checkbox
          handleChange={() => this.handleChange(x.name, !this.state[x.name]) }
          className={this.state[x.name] ? 'checked-class' : '' }
        />))
    }
    </div>
  )
}

通过这样做 :

this.state[name]

You can look at Object.keys() , but if in future you would need to handle more than one state, iteration does not seem to solve the problem.您可以查看Object.keys() ,但如果将来您需要处理多个状态,迭代似乎并不能解决问题。

You could also give it a prefix [name_${name}]: checked , but would not recommend that at all.您也可以给它一个前缀[name_${name}]: checked ,但根本不建议这样做。

If it is not a problem, use an object and you will have full controll over it.如果它不是问题,请使用一个对象,您将完全控制它。

this.setState({
  something: {
    name,
    checked  
  },
})

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

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