受控和非受控 input

  1. // 受控
  2. const NotePart: React.FC = () => {
  3. const note = props.value;
  4. const onChange: ChangeEventHandler<HTMLInputElement> = (e) => {
  5. props.onChange(e.target.value);
  6. return (
  7. <Wrapper>
  8. <div>备注:<input value={note} onChange={(e) => setNote(e.target.value)} type="text" placeholder="请输入备注"/></div>
  9. </Wrapper>
  10. );
  11. };
  12. // 非受控
  13. const NotePart: React.FC = (props) => {
  14. const [note, setNote] = useState('');
  15. const refInput = useRef<HTMLInputElement>(null);
  16. const onBlur = () => {
  17. if (refInput.current !== null) {
  18. setNote(refInput.current.value);
  19. }
  20. };
  21. return (
  22. <Wrapper>
  23. <div>备注:<input ref={refInput} defaultValue={note} onBlur={onBlur} type="text" placeholder="请输入备注"/></div>
  24. </Wrapper>
  25. );
  26. };

实现爷爷组件读取操作孙子组件

爷爷组件

  1. const [selected, setSelected] = useState({
  2. tags: [] as number[],
  3. note: '',
  4. category: '-' as Category,
  5. amount: '0'
  6. });
  7. const onChange = (obj: Partial<typeof selected>) => {
  8. setSelected({
  9. ...selected,
  10. ...obj
  11. });
  12. };
  13. return (
  14. <LayoutWrapper>
  15. {selected.tags}
  16. --
  17. {selected.note}
  18. --
  19. {selected.category}
  20. --
  21. {selected.amount}
  22. <HeaderSection value={selected.tags} onChange={(tags) => {onChange({tags});}}/>
  23. <RecordsSection
  24. note={selected.note} onChangeNote={(note) => {onChange({note});}}
  25. category={selected.category} onChangeCategory={(category) => {onChange({category});}}
  26. amount={selected.amount} onChangeAmount={(amount) => {onChange({amount});}}
  27. />
  28. </LayoutWrapper>
  29. );
  30. }

父亲组件

  1. type Props = {
  2. note: string,
  3. category: '-' | '+',
  4. amount: string,
  5. onChangeNote: (note: string) => void
  6. onChangeAmount: (amount: string) => void
  7. onChangeCategory: (category: '-' | '+') => void
  8. }
  9. const RecordsSection: React.FC<Props> = (props) => {
  10. let history = useHistory();
  11. const submit = () => {
  12. alert('保存成功');
  13. history.push('/');
  14. };
  15. return (
  16. <Wrapper>
  17. <SelectionPart {...props}/>
  18. <NotePart {...props}/>
  19. <NumberPadPart{...props}/>
  20. </Wrapper>
  21. );
  22. };
  23. export default RecordsSection;

孙子组件

SelectionPart 组件 使用

  1. // SelectionPart 组件
  2. type Props = {
  3. category: '-' | '+',
  4. onChangeCategory: (category: '-' | '+') => void
  5. }
  6. const SelectionPart: React.FC<Props> = (props) => {
  7. const categoryMap = {'-': '支出', '+': '收入'};
  8. type keys = keyof typeof categoryMap
  9. const [categoryList] = useState<keys[]>(['-', '+']);
  10. const category = props.category;
  11. return (
  12. <Wrapper>
  13. {categoryList.map((c, index) =>
  14. <div className={category === c ? 'selected' : ''} onClick={() => {props.onChangeCategory(c);}} key={index}>
  15. {categoryMap[c]}
  16. </div>
  17. )}
  18. </Wrapper>
  19. );
  20. };
  21. export default SelectionPart;

NotePart组件使用

  1. // NotePart组件
  2. type Props = {
  3. note: string,
  4. onChangeNote: (value: string) => void
  5. }
  6. const NotePart: React.FC<Props> = (props) => {
  7. const {note} = props;
  8. const refInput = useRef<HTMLInputElement>(null);
  9. const onBlur = () => {
  10. if (refInput.current !== null) {
  11. props.onChangeNote(refInput.current.value);
  12. }
  13. };
  14. return (
  15. <Wrapper>
  16. <div>备注:<input ref={refInput} defaultValue={note} onBlur={onBlur} type="text" placeholder="请输入备注"/></div>
  17. </Wrapper>
  18. );
  19. };
  20. export default NotePart;

NumberPadPart 组件使用

  1. // NumberPadPart组件
  2. type Props = {
  3. amount: string,
  4. onChangeAmount: (amount: string) => void
  5. }
  6. const NumberPadPart: React.FC<Props> = (props) => {
  7. const [output, _setOutput] = useState<string>('0');
  8. const setOutput = (output: string) => {
  9. if (output.length > 16) {
  10. output = output.slice(0, 16);
  11. } else if (output.length === 0) {
  12. output = '0';
  13. }
  14. _setOutput(output);
  15. props.onChangeAmount(output);
  16. };
  17. ......