skip to Main Content

I’m building a hook for data ordering, and it can receive state and setState from outside, defined by the user, but if they are not passed, I use an internal useState declaration.

But is this approach recommended? As follows:

export function useMaterialTableSort(data, columns, orderState, setOrderState) {

    if (orderState && setOrderState) {
        var columnOrder = orderState
        var setColumnOrder = setOrderState
    }
    else if (!orderState && !setOrderState) {
        var [columnOrder, setColumnOrder] = useState({})
    }
    else {
        throw Error("orderState and setOrderState must be defined!")
    }

    // rest of the component that uses columnOrder and setColumnOrder state
}

The other alternative would be to use an aligned state to update according to the outside state, but this would cause two renders

export function useMaterialTableSort(data, columns, orderState, setOrderState) {
    const [columnOrder, setColumnOrder] = useState(orderState || {})

    useEffect(() => {
        if (typeof orderState === "object") {
            setColumnOrder(orderState)
        }
    }, [orderState])

    // In the rest of the component, instead of using setColumnOrder, 
    //  which would cause a rendering loop, I would use setOrderState, 
    //   which is an outside state
}

2

Answers


  1. Calling useState conditionally breaks the rules of React hooks – it may work in practice, because a the caller of your function will likely consistently either supply or not supply orderState / setOrderState, but I would not recommend it.

    You can re-write your hook like this:

    export function useMaterialTableSort(data, columns, orderState, setOrderState) {
    
        const [internalOrderState, setInternalOrderState] = useState({});
    
        const [columnOrder,  setColumnOrder] = orderState && setOrderState 
            ? [orderState, setOrderState]
            : [internalOrderState, setInternalOrderState];
    
        // rest of the component that uses columnOrder and setColumnOrder state
    }
    
    
    Login or Signup to reply.
  2. since at the end of the day you want to order data you can just order it internally and return setColumnOrder to allow the user to also do moification outside the hook without needing to redeclare a use State

    export function useMaterialTableSort(data, columns, orderState, setOrderState) {
    
    const [internalOrderState, setInternalOrderState] = useState({});
    
    const [columnOrder,  setColumnOrder] = useState({})
    // rest of the component that uses columnOrder and setColumnOrder state
    
        return {
                orderedData://the data after ordering,
                setColumnOrder
               }
    

    }

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search