首页 > 解决方案 > 各有什么办法

  • 在一个
  • 问题描述

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

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

    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>
      )
    }
    

    标签: javascriptcssreactjs

    解决方案


    isHidden您的应用程序中有两种。我将上下文中的那个称为global hidden isAllHiddenlocal hidden<Booking />中的那个。 isHidden

    问题是你滥用这两者。局部隐藏是 的内部状态<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>
      )
    }
    

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


    推荐阅读