繁体   English   中英

每个人可以通过什么方式<li>在一个<ul>改变它的类名而不影响其他人?

[英]In what way can each <li> in a <ul> change its classname without affecting the others?

这里会有不寻常的代码量,因为我试图分享正在发生的一切。

我想做的是......在一个列表中:

  1. 将服务标记为完成。
  2. 完成后更改它们的颜色并隐藏。
  3. 按下按钮显示隐藏的服务。

我设法隐藏了每个单独的服务,但无法使用隐藏/显示所有已完成服务的按钮。

我有一个上下文提供程序:

const ContextBooking = React.createContext()

const ContextProviderBooking = ({ children }) => {
  const [isHidden, setIsHidden] = useState(false); //sharing among both components to hide/show list

  return <ContextBooking.Provider value={{ isHidden, setIsHidden }}>
    {children}
  </ContextBooking.Provider>
}
export { ContextBooking, ContextProviderBooking }

这是通过另一个文件中的 BookingsDisplay 组件传递的

...
<ContextProviderBooking>
      <BookingsDisplay /> //this encapsulates each <Booking />
</ContextProviderBooking>
...

我正在一个名为“BookingsDisplay”的更大组件中呈现每个服务

const BookingsDisplay = () => {
  const { isHidden, setIsHidden } = useContext(ContextBooking)  
  const display = day => //function that displays each service according to the day it was booked for
    allBookings.map( //allBookings is a json file
      item =>
        item.day === day && ( 
          <Booking
            isHidden={isHidden}
            completed={item.completed} //comes from json file, all default to false
            key={item.id}
            id={item.id}
            time={item.time}
            name={item.name}
            date={item.date} 
          />
        )
    )
  return (
    <div className="bookings">
      <h2 className="ib">Next bookings</h2>
      <button //This won't work as expected and hide/show all of the 'completed' bookings
          onClick={() =>{ 
            setIsHidden(!isHidden);}
      }>
          Show hidden  
      </button>
      <h2>Today</h2>      
      <ul> {display('today')} </ul>
      <h2> Tomorrow </h2>
      <ul> {display('tomorrow')} </ul>
      <h2> General </h2>
      <ul> {display('other')} </ul>
    </div>
  )
}

每个“预订”组件都有一个按钮,用于将服务标记为完成。 这是通过有条件地更改每个组件的类来实现的。 就我而言,这很好用

const Booking = (props) => {
  const [isHidden, setIsHidden] = useState(props.isHidden)
  console.log(props.isHidden) // will output true or false 16 times(there are 16 component in total)
  const [isCompleted, setIsCompleted] = useState(props.completed);
  return (
    <li
      className={
        isCompleted && isHidden ? 'booking-complete hide' //class names are not changing individually
        : isCompleted ? 'booking-complete'                //if button is pressed on one of them,
        : 'booking'                                       //it may affect the other
      }
      key={props.id}
      id={props.id}>
      <h3>{props.date}</h3>
      <h4>{props.time}</h4>
      <h5>{props.name}</h5>
      <button
        onClick={() => { //shouldn't this button work of each li and not sometimes all of them?
          if (!isCompleted && !isHidden) { 
            setIsCompleted(!isCompleted); //this changes color of the service as className changes
            setTimeout(() => setIsHidden(!isHidden), 200) //after a short time it is hidden
          }
          else if (isCompleted && !isHidden) {
            setIsCompleted(!isCompleted);
          }
          else {
            setIsCompleted(!isCompleted);
            setIsHidden(!isHidden);
          }
        }}>
        {!isCompleted ? `Completed` : `Not complete`}
      </button>
    </li>
  )
}

您的应用中有两种isHidden 我将上下文中的一个称为全局隐藏isAllHidden ,将<Booking />称为本地隐藏isHidden

问题是你滥用了两者。 local hidden<Booking />的内部状态。 它存在的原因是因为你需要 200ms 的动画延迟,否则可以用isCompleted代替。 所以它应该派生自isCompleted而不是isAllHidden

修复 1:

const Booking = (props) => {
  const [isHidden, setIsHidden] = useState(props.completed)
}

现在全局隐藏局部隐藏结合起来决定一个预订是否应该隐藏。 你的逻辑应该反映这个事实。

修复 2:

  const shouldBeHidden = Boolean(props.isAllHidden && isHidden)

  return (
    <li
      className={
        isCompleted && shouldBeHidden ? 'booking-complete hide' 
        : isCompleted ? 'booking-complete'on one of them,
        : 'booking'other
      }
    >
  ...

放在一起:

const Booking = (props) => {
  const [isHidden, setIsHidden] = useState(props.completed)
  const [isCompleted, setIsCompleted] = useState(props.completed)

  const shouldBeHidden = props.isAllHidden && isHidden

  return (
    <li
      className={
        isCompleted && shouldBeHidden ? 'booking-complete hide' //class names are not changing individually
        : isCompleted ? 'booking-complete'                //if button is pressed on one of them,
        : 'booking'                                       //it may affect the other
      }
    >
      <input type='checkbox' checked={isCompleted} onChange={() => {
        setIsCompleted(!isCompleted)
        setTimeout(() => setIsHidden(!isHidden), 200)
      }}/>
      <span>{props.name}</span>
    </li>
  )
}

我在这里设置了一个演示板来显示结果。

暂无
暂无

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

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