React Typescript 故事书使用 onChange callBack 然后 setState 值 backTo Input 实现自定义 Input 组件

IT技术 reactjs typescript react-hooks storybook use-state
2022-07-12 01:04:40

我目前正在用故事书实现一个 React Customized Input 组件。我希望实现的是这个自定义的 Input 组件将需要很少的 args,其中一个 args 是onChangeInput,稍后它将负责为“input value”设置状态值,下面是我的主要 Input 组件实现:

输入.tsx

import React from 'react'

export type Props = {
  /**
   * This is the Label text value
   */
  labelText?: string,
  /**
   * Placeholder text for input
   */
  placeholder?: string,
  /**
   * Classes defined here will be appended to the input's default classes
   */
  className?: string,
  /**
   * Value attribute of Input
   */
  value?: string,
  /**
   * Name attribute of Input
   */
  name?: string,
  /**
   * Label for attribute
   */
  htmlFor?: string,
  /**
   * Callback for when user typing in Input
   */
  onChangeInput: any,
}

/**
 * Generic input component.
 */
export function Input({labelText, placeholder='', className='', value='', name='', htmlFor='', onChangeInput}:Props) {    
    return (
        <div>
            <label className='text-text-01-normal font-medium text-sm leading-5' htmlFor={htmlFor}>
                {labelText}
            </label>
            <div className="relative">
                <input
                    id={htmlFor}
                    className={[
                        "relative w-64 pl-3 h-8 py-2 border rounded bg-ui-03 border-ui-06 text-text-01-normal leading-5 text-sm text-left hover:bg-ui-03 hover:border-ui-07 focus:bg-ui-03 focus:outline-none focus:border-interactive-01-active active:bg-ui-03",                        
                        className
                        ].join(' ')} 
                    placeholder={placeholder}
                    value={value}
                    name={name}
                    onChange={ (e) => { onChangeInput(e.target.value) }}
                />
            </div>
        </div>
    )
}   

然后在我的故事书文件中,我希望有一个钩子useStatelocalValueonChangeInput作为方法传递给自定义输入组件时,输入的本机 onChange 将开始让它 setState 为 localValue ,所以我自定义的输入组件可以将输入值显示为用户输入...

输入.stories.tsx

import React, { useState } from 'react';
import { Story, Meta } from '@storybook/react';
import { withDesign } from 'storybook-addon-designs'

import { Input, Props } from './Input';

const [localValue, setValue] = useState<string>('');
const onChangeInput = (inputValue: string) => {
    console.log(inputValue);
    setValue(inputValue);
}

export default {
  title: 'General/Input',
  component: Input,
  decorators: [withDesign],
  parameters: {
    design: {
      type: 'figma',
    },
  },
} as Meta;

const Template: Story<Props> = (args:Props) => <Input {...args} />;

export const Default: Story<Props> = Template.bind({});
Default.args = {
  labelText: 'Label',
  placeholder: 'Placeholder',
  name: 'test-name',  
  htmlFor: 'test-for',
  value: localValue,
  onChange: onChangeInput,
} as Partial<Props>;
Default.parameters = {
  design: {
    url: 'https://www.figma.com/to-some-design-url'
  }
}

但不幸的是我无法让它工作,所以在这里寻求帮助,请提供代码示例,谢谢

1个回答

经过我自己的一番调查。Input.tsx 文件没有问题。只是对故事书有一些误解。以下是解决方案,工作正常,对于将来搜索相同问题的任何人,请随时复制粘贴到您自己的项目中:) 谢谢

import React, { useState } from 'react';
import { Story, Meta } from '@storybook/react';
import { withDesign } from 'storybook-addon-designs'

import { Input, Props } from './Input';

export default {
  title: 'General/Input',
  component: Input,
  decorators: [withDesign],
  parameters: {
    design: {
      type: 'figma',
    },
  },
} as Meta;

const Template: Story<Props> = () => {    
    const [localValue, setValue] = useState<string>('');
    const onChangeInput = (inputValue: string) => {
        setValue(inputValue);
    }
    return (
        <Input 
            labelText='Label'
            placeholder='Placeholder'
            className='test-class-name'
            name='test-name'            
            value={localValue}
            htmlFor='test-for'
            onChangeInput={ onChangeInput }
        />
    )
}

export const Default: Story<Props> = Template.bind({});
Default.parameters = {
  design: {
    url: 'https://www.figma.com/link-to-design'
  }
}