3

我为我的反应项目设置了故事书,我有 2 个故事。一个是一个简单的按钮和一个更大的组件。我对两者都使用了旋钮,它在简单按钮上工作得很好,但它不会更新更大的组件(withInfo 插件实际上显示了来自旋钮的正确更新信息,但组件没有更新。)这告诉我有问题我的组件而不是故事书旋钮。但是该组件在我的应用程序中似乎工作得很好。

我的按钮故事

  .add('with text', () => {
    const buttonText = text('Button Text', 'Hello Button');
    return (
      <Button onClick={action('clicked')}>{buttonText}</Button>)
  })

我更大的组件故事

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

组件

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;

我的故事书配置

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

我的 addons.js

import '@storybook/addon-actions/register';
import '@storybook/addon-knobs/register';
import '@storybook/addon-links/register';
import '@storybook/addon-actions/register';
4

1 回答 1

3

您的组件仅在您获得初始状态时才使用道具,您甚至在渲染期间都没有使用它们。

一种反模式 - https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html

也不完全是我所说的“纯”组件 - https://reactjs.org/docs/react-api.html#reactpurecomponent

除非您实际更新您的状态(您在处理程序中执行此操作),否则您不会看到基于这些道具的更新。

也就是说,如果您希望继续沿着这条路走下去,您将需要一种方法来对这些道具更改做出反应。您可以利用 componentWillReceiveProps 生命周期并在此处调用 setState。

于 2019-08-12T20:59:28.080 回答