如何将值从 child 组件传递到 TSX 中的 parent?

How to pass value from child component to parent in TSX?

Parent 组件有这个

 value={this.onUpdate(index)}

并且 onUpdate 会处理值和索引

在 child 组件中,我有一个输入字段

onChange={this.handleText(index)}

这会调用一个方法来发送道具

this.props.value(sum);

而且我在想我需要为价值做接口,但是怎么做呢?

编辑: Parent:

import * as React from "react";
import styled from 'styled-components';
import ShoppingList from './ShoppingList';

const Container = styled.div`
  position:absolute;
  left:0;
  bottom:0;
  right:0;
  display: flex;
  flex-direction: row;
  justify-content: space-between;
`;

interface Item {
  id: number;
  value: number;
}

interface TPState {
  shoppingLists2: object[];
  shoplistsums: Item[];
  sum: number;
}

class TotalPrice extends React.Component<{}, TPState> {
  constructor(props: {}) {
    super(props);
    this.state = {
      shoppingLists2: [ShoppingList],
      sum: 0,
      shoplistsums: []
    }
  }

  AddShoppingList = () => {
    let shoppingLists2 = this.state.shoppingLists2.concat(ShoppingList);
    console.log(shoppingLists2)
    this.setState({
      shoppingLists2,
    })
  }

  onUpdate = index => (value) => {
    console.log('index, value', index, value)
    let item: Item = {
      id: index,
      value: value
    }
    let shoplistsums = [...this.state.shoplistsums];
    var indexOfItem = shoplistsums.map(e => e.id).indexOf(item.id);
    if (indexOfItem === -1) {
      shoplistsums.push(item);
    }
    else {
      shoplistsums[indexOfItem] = item;
    }
    let sum = shoplistsums.map(this.amount).reduce(this.sum);
    this.setState({
      shoplistsums,
      sum
    })
  }

  amount(item) {
    return item.value;
  }

  sum(prev, next) {
    return prev + next;
  }

  render() {
    return (
      <div>
        {this.state.shoppingLists2.map((ShoppingList, index) => (
          <ShoppingList
            key={index}
            value={this.onUpdate(index)}
          />
        ))}
        <Container>
          <label>Total:</label>
          <label>{this.state.sum + ' €'}</label>
          <button onClick={this.AddShoppingList}>Add Receipt</button>
        </Container>
      </div>
    );
  }
}

export default TotalPrice;

Child

import * as React from "react";
import styled from 'styled-components';

const Container = styled.div`
  display: flex;
  flex-direction: row;
  justify-content: space-between;
`;

export interface SLProps {
}

interface SLState {
  smallList: number[];
  sum: number;
}

export default class ShoppingList extends React.Component<SLProps, SLState> {
  constructor(props: SLProps) {
    super(props);
    this.state = {
      smallList: [0],
      sum: 0
    }
  }

  handleText = i => e => {
    let smallList = [...this.state.smallList];
    let x = e.target.value;
    if (isNaN(parseFloat(x))) {
      smallList[i] = 0;
    }
    else {
      smallList[i] = parseFloat(x);
    }
    let sum = smallList.reduce(function(a, b) {
      return a + b;
    });
    this.props.value(sum);
    this.setState({
      smallList,
      sum
    })
  }

  addExpense = e => {
    e.preventDefault()
    let smallList = this.state.smallList.concat([0])
    this.setState({
      smallList
    })
  }

  render() {
    return (
      <div>
        <Container>
          <select>
            <option value="food">Food</option>
            <option value="houseware">Houseware</option>
            <option value="entertainment">Entertainment</option>
          </select>
          <button onClick={this.addExpense}>Add expense</button>
        </Container>
        {this.state.smallList.map((question, index) => (
          <Container key={index}>
            <input
              type="text"
            />
            <input
              type="number"
              step="0.01"
              onChange={this.handleText(index)}
              value={question === 0 ? '' : question}
            />
          </Container>
        ))}
        <Container>
          <label>Total:</label>
          <label>{this.state.sum + ' €'}</label>
        </Container>
      </div>
    )
  }
}
export interface SLProps {
  value: (value: number) => void
}