0

At the moment in my component I am setting the default value to 'null', but I am trying to default the active states value to the first object in the objects which is part of the state, a bit confused.

code so far:

import React from 'react';

interface ActiveObject {
    id: number;
    title: string;
    function(index: number): void;
};

interface ButtonGroupState {
    activeObject: ActiveObject | null;
    objects: ActiveObject[];
};

const ButtonGroup: React.FunctionComponent = () => {

    const [active, setActive] = React.useState<ButtonGroupState>({
        activeObject: null,
        objects: [{
            id: 1,
            title: '1 Week',
            function(index: number) {
                setActive({ ...active, activeObject: active.objects[index] })
            }

        }, {
            id: 2,
            title: '1 Month',
            function(index: number) {
                setActive({ ...active, activeObject: active.objects[index] })

            }
        }, {
            id: 3,
            title: '3 Months',
            function(index: number) {
                setActive({ ...active, activeObject: active.objects[index] })

            }
        }]
    })

    const toggleActiveStyles = (index: number) => {
        if (active.objects[index] === active.activeObject) {
            return "btn-active"
        } else {
            return " btn-plain"
        }
    }

    return (
        <> <div className="wrapper">
            {active.objects.map((inner, index) => 
                <button type="button" className={toggleActiveStyles(index)} onClick={() => inner.function(index)} key={inner.id}>{inner.title}</button>
            )}
        </div>
        </>

    )
}

export default ButtonGroup;
5
  • 1
    what is your problem? Commented Sep 2, 2021 at 15:36
  • At the moment the active state defaults to null, how would I default the active state to the first item/object? Commented Sep 2, 2021 at 15:39
  • First item/object? What first item or object are you referring to? Why can you just specify whatever it is you need to reference as the active value? Commented Sep 2, 2021 at 15:41
  • In the state there are objects with id, title etc Commented Sep 2, 2021 at 15:42
  • activeObject: objects[0] 🤔 Commented Sep 2, 2021 at 15:48

2 Answers 2

1

I suggest you move objects into a variable and set it's first element to activeObject

import React from 'react';

interface ActiveObject {
    id: number;
    title: string;
    function(index: number): void;
};

interface ButtonGroupState {
    activeObject: ActiveObject | null;
    objects: ActiveObject[];
};

const ButtonGroup: React.FunctionComponent = () => {
    const objectsArray = [{
            id: 1,
            title: '1 Week',
            function(index: number) {
                setActive({ ...active, activeObject: active.objects[index] })
            }

        }, {
            id: 2,
            title: '1 Month',
            function(index: number) {
                setActive({ ...active, activeObject: active.objects[index] })

            }
        }, {
            id: 3,
            title: '3 Months',
            function(index: number) {
                setActive({ ...active, activeObject: active.objects[index] })

            }
        }];

    const [active, setActive] = React.useState<ButtonGroupState>({
        activeObject: objectsArray[0],
        objects: objectsArray
    })

    const toggleActiveStyles = (index: number) => {
        if (active.objects[index] === active.activeObject) {
            return "bp-active"
        } else {
            return " btn-plain"
        }
    }

    return (
        <> <div className="wrapper">
            {active.objects.map((inner, index) => 
                <button type="button" className={toggleActiveStyles(index)} onClick={() => inner.function(index)} key={inner.id}>{inner.title}</button>
            )}
        </div>
        </>

    )
}

export default ButtonGroup;
Sign up to request clarification or add additional context in comments.

1 Comment

That actually makes more sense, thank you!
0

You can either duplicate the first element data as the initial state. Note: factoring the array definition out would be an optimization.

const ButtonGroup: React.FunctionComponent = () => {
  const [active, setActive] = React.useState<ButtonGroupState>({
    activeObject: {
      id: 1,
      title: '1 Week',
      function(index: number) {
        setActive({ ...active, activeObject: active.objects[index] })
      }
    },
    objects: [{
      id: 1,
      title: '1 Week',
      function(index: number) {
        setActive({ ...active, activeObject: active.objects[index] })
      }
    }, {
      id: 2,
      title: '1 Month',
      function(index: number) {
        setActive({ ...active, activeObject: active.objects[index] })

      }
    }, {
      id: 3,
      title: '3 Months',
      function(index: number) {
        setActive({ ...active, activeObject: active.objects[index] })
      }
    }]
  });

or use an useEffect hook to set it on the initial render.

React.useEffect(() => {
  setActive(active[0]);
}, []);

Note

You appear to have a logical bug with the functions where they will have stale enclosures the active and activeObject state. This may be ok for the active.object if it's never updated. Since it's the same function for each element you should factor this out so your code is more DRY, and use a functional update.

You likely also don't what to duplicate state. Just store the active id (or index) and reference this in your code when accessing/passing props.

const setActive = (index: number) => {
  setActive(active => ({
    ...active,
    activeObject: index,
  }));
}

Then use/pass setActive as a prop where you need to.

...
activeObject={active.objects[active.activeObject]}
setActive={setActive}
...

1 Comment

Thanks that is a way I was thinking, but I think I over thought on it, so got confused.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.