I can't seem to figure out how to get my event handling function to do its logic to update the UI AND storybook's addon - actions()
to log the output.
The reason I want the UI to update is because we're using cypress.io for testing. We've hacked/stubbed the actions messaging (pretty cool, window.postMessage) to access the action message which allows the use of action("functionName")
, instead of wiring up a event handling function in [file].stories.tsx
. I'd like to do both for my sanity. To check the action message, its a few clicks. I'd rather just see the item get removed. With that, for testing, I'd like to expect the action message (I'm able to do that). We are using alert()
to check if something fired, and I'm not a fan.
If this just seems unnecessary, or counter intuitive/productive, do elaborate.
If it helps... <List />
is just that, but has an action button on each item to remove the item from the list.
Using onRemove={actionHandler}
prop, below, in List does just that in the UI, removes the item and Cypress is happy, but need the alert()
to track. But cant wire up the action()
anywhere and no log in the GUI.
If I REMOVE onRemove={actionHandler}
and unment // onRemove: action("removeItem")
, I get the action log I want, but the Item doesn't remove.
I understand actions are supposed to mimic event handler's, but I'd like it to do that AND fire the actual event... if possible or reasonable.
List.stories.tsx
// storybook addons
import { withKnobs } from "@storybook/addon-knobs";
// deps
import React from "react";
import { action } from "@storybook/addon-actions";
// utils
import { CustomEvent } from "../../hooks";
// ponents
import { Item } from "./Item"
import { List } from "./ListItems"
import { InputHeader } from "../inputs/InputHeader";
// create test states for target dropdown
export default {
ponent: List,
title: "Lists|With Action",
decorators: [withKnobs]
};
const listItemsData = {
values: ['Test Value 1', 'Test Value 2', 'Test Value 3', 'Test Value 4', 'Test Value 5'],
name: "test list story",
// onRemove: action("removeItem")
};
export const listWithActionButton = () => {
const [listItemState, setListItemState] = React.useState(listItemsData)
const actionHandler = (event: CustomEvent<string[]>) => {
// action("removeItem")()
setListItemState(prevState => ({
...listItemState,
values: event.target.value,
}))
};
return (
<>
<InputHeader headerText="List with Action Buttons" />
<br/>
<List
{...listItemState}
onRemove={actionHandler}
/>
</>
)
};
List.tsx
export const List = ({name, values, onRemove}) => {
const removeItem = (index: number) => {
// this is what I want to fire AS WELL as the action log.
const top = values.slice(0, index);
const bottom = values.slice(index + 1);
const updatedOptions = [...top, ...bottom]
// Fire a custom event to match what our useForm hook expects
const event: CustomEvent<string[]> = {
target: {
value: updatedOptions,
name
},
};
return onRemove(event);
};
return (
<ListStyle>
{
values.map((item, index) => {
return (
<Item
key={index}
value={item}
removeItem={removeItem}
itemIndex={index}
/>)
})
}
</ListStyle>
)
};
I can't seem to figure out how to get my event handling function to do its logic to update the UI AND storybook's addon - actions()
to log the output.
The reason I want the UI to update is because we're using cypress.io for testing. We've hacked/stubbed the actions messaging (pretty cool, window.postMessage) to access the action message which allows the use of action("functionName")
, instead of wiring up a event handling function in [file].stories.tsx
. I'd like to do both for my sanity. To check the action message, its a few clicks. I'd rather just see the item get removed. With that, for testing, I'd like to expect the action message (I'm able to do that). We are using alert()
to check if something fired, and I'm not a fan.
If this just seems unnecessary, or counter intuitive/productive, do elaborate.
If it helps... <List />
is just that, but has an action button on each item to remove the item from the list.
Using onRemove={actionHandler}
prop, below, in List does just that in the UI, removes the item and Cypress is happy, but need the alert()
to track. But cant wire up the action()
anywhere and no log in the GUI.
If I REMOVE onRemove={actionHandler}
and unment // onRemove: action("removeItem")
, I get the action log I want, but the Item doesn't remove.
I understand actions are supposed to mimic event handler's, but I'd like it to do that AND fire the actual event... if possible or reasonable.
List.stories.tsx
// storybook addons
import { withKnobs } from "@storybook/addon-knobs";
// deps
import React from "react";
import { action } from "@storybook/addon-actions";
// utils
import { CustomEvent } from "../../hooks";
// ponents
import { Item } from "./Item"
import { List } from "./ListItems"
import { InputHeader } from "../inputs/InputHeader";
// create test states for target dropdown
export default {
ponent: List,
title: "Lists|With Action",
decorators: [withKnobs]
};
const listItemsData = {
values: ['Test Value 1', 'Test Value 2', 'Test Value 3', 'Test Value 4', 'Test Value 5'],
name: "test list story",
// onRemove: action("removeItem")
};
export const listWithActionButton = () => {
const [listItemState, setListItemState] = React.useState(listItemsData)
const actionHandler = (event: CustomEvent<string[]>) => {
// action("removeItem")()
setListItemState(prevState => ({
...listItemState,
values: event.target.value,
}))
};
return (
<>
<InputHeader headerText="List with Action Buttons" />
<br/>
<List
{...listItemState}
onRemove={actionHandler}
/>
</>
)
};
List.tsx
export const List = ({name, values, onRemove}) => {
const removeItem = (index: number) => {
// this is what I want to fire AS WELL as the action log.
const top = values.slice(0, index);
const bottom = values.slice(index + 1);
const updatedOptions = [...top, ...bottom]
// Fire a custom event to match what our useForm hook expects
const event: CustomEvent<string[]> = {
target: {
value: updatedOptions,
name
},
};
return onRemove(event);
};
return (
<ListStyle>
{
values.map((item, index) => {
return (
<Item
key={index}
value={item}
removeItem={removeItem}
itemIndex={index}
/>)
})
}
</ListStyle>
)
};
Share
Improve this question
edited Jan 10, 2020 at 11:57
ouflak
2,52310 gold badges45 silver badges52 bronze badges
asked Jan 9, 2020 at 17:10
AJdevsAJdevs
411 silver badge7 bronze badges
1
-
onRemove={(...args) => { action('log'); actionHandler(...args); }}
? – Emile Bergeron Commented Jan 9, 2020 at 17:15
1 Answer
Reset to default 6You can do something like this if you want to fire an action AND execute your function.
<Button
onClick={(e) => {
action('click')(e);
removeItem();
}}
selected={state}
>