I have setup storybook for my react project, and i have 2 stories. One that is a simple button and a larger component. I use knobs for both, it works fine of the simple button but it dose not update the larger component (The withInfo addon actaully shows the correct updated information from knobs, but the component dose not update.) This tells me there is something wrong with my component and not storybook knobs. But the component seems to work just fine in my application.
My Button story
.add('with text', () => {
const buttonText = text('Button Text', 'Hello Button');
return (
<Button onClick={action('clicked')}>{buttonText}</Button>)
})
My larger component story
import React from 'react';
import { storiesOf } from '@storybook/react';
import { text, number, file, boolean } from '@storybook/addon-knobs/react';
import blueSignImage from '../src/images/sign-3.jpg';
import SignType from '../src/components/SignType/index';
storiesOf('Sign Type', module)
.add('With current signs and requested signs', () => {
const typeId = text("Type id", "test-1234");
const availableSigns = number('Avalible Signs', 5);
const requestedSigns = number('Requested Signs', 3);
const typeName = text("Type name", "Blue Sign Image");
const isSaving = boolean("Is saving", false);
const onRequsetSigns = (id, value) => {
console.log("Got requset for " + value + " signs for id " + id);
};
return (
<SignType typeId={typeId}
availableSigns={availableSigns}
requestedSigns={requestedSigns}
typeName={typeName}
image={blueSignImage}
isSaving={isSaving}
onRequsetSigns={onRequsetSigns}
/>
)
});
The component
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { Card, CardContent, CardMedia, Typography, Button, Slider, LinearProgress } from '@material-ui/core';
import SendIcon from '@material-ui/icons/Send';
import CloseIcon from '@material-ui/icons/Close';
import "./index.scss";
class SignType extends PureComponent {
constructor(props) {
super(props);
this.state = {
typeId: props.typeId,
typeName: props.typeName,
image: props.image,
availableSigns: props.availableSigns,
requestedSigns: props.requestedSigns,
isSaving: props.isSaving,
onRequsetSigns: props.onRequsetSigns,
// Local Vars
requestAmount: 5,
showOrderMore: false,
};
this.onOrderMoreClicked = this.onOrderMoreClicked.bind(this);
this.onHideOrderMore = this.onHideOrderMore.bind(this);
this.onRequestAmountChanged = this.onRequestAmountChanged.bind(this);
this.onSaveRequest = this.onSaveRequest.bind(this);
}
componentDidMount() {
}
onOrderMoreClicked() {
this.setState({ showOrderMore: true });
}
onHideOrderMore() {
this.setState({ showOrderMore: false });
}
onRequestAmountChanged(event, value) {
this.setState({ requestAmount: value });
}
onSaveRequest() {
this.setState({ showOrderMore: false });
this.state.onRequsetSigns(this.state.typeId, this.state.requestAmount);
}
render() {
const { typeId, availableSigns, requestedSigns, image, typeName, showOrderMore, isSaving, requestAmount } = this.state;
return (
<Card className="signType">
<CardMedia
className="cover"
image={image}
title="Live from space album cover"
/>
<div className="details">
<CardContent className="content">
<Typography component="h5" variant="h5">
{typeName}
</Typography>
<Typography variant="body1" color="textPrimary">
{availableSigns} signs available
{!showOrderMore && !isSaving && (
<Button color="primary" onClick={this.onOrderMoreClicked}>
Order more
</Button>)}
</Typography>
{requestedSigns > 0 && (
<Typography variant="subtitle2" color="textSecondary">
{requestedSigns} requested signs pending
</Typography>
)}
</CardContent>
{showOrderMore && (
<div className="requestSignsControl">
<Typography id={"request-slider-" + typeId} variant="h6" color="textPrimary">
Request additional signs
</Typography>
<Slider
defaultValue={5}
aria-labelledby={"request-slider-" + typeId}
valueLabelDisplay="auto"
step={1}
marks
min={1}
max={25}
onChangeCommitted={this.onRequestAmountChanged}
/>
<div>
<Button variant="contained" color="secondary" onClick={this.onHideOrderMore} className="icon">
<CloseIcon className="icon" />
</Button>
<Button variant="contained" color="primary" onClick={this.onSaveRequest} className="icon">
Send Request
<SendIcon className="icon" />
</Button>
</div>
</div>
)}
{isSaving && <LinearProgress />}
</div>
</Card>
);
}
}
SignType.propTypes = {
typeId: PropTypes.string.isRequired,
typeName: PropTypes.string.isRequired,
image: PropTypes.string.isRequired,
availableSigns: PropTypes.number.isRequired,
requestedSigns: PropTypes.number.isRequired,
isSaving: PropTypes.bool.isRequired,
onRequsetSigns: PropTypes.func.isRequired,
};
export default SignType;
My storybook config
import { configure, addDecorator } from '@storybook/react';
import { withKnobs } from '@storybook/addon-knobs';
import { withInfo } from '@storybook/addon-info';
import { withConsole } from '@storybook/addon-console';
import 'typeface-roboto';
// automatically import all files ending in *.stories.js
const req = require.context('../stories', true, /\.stories\.js$/);
function loadStories() {
req.keys().forEach(filename => req(filename));
}
addDecorator(withInfo);
addDecorator(withKnobs);
addDecorator((storyFn, context) => withConsole()(storyFn)(context));
configure(loadStories, module);
my addons.js
import '@storybook/addon-actions/register';
import '@storybook/addon-knobs/register';
import '@storybook/addon-links/register';
import '@storybook/addon-actions/register';