0

これは私のコンポーネント構造です: ExchangeRateInput ExhangeRateValueInput ExhangeRateDialog

open inの状態は、prop としてExhangeRateDialogに渡されます。しかし、私がExchangeRateInputでsetState open を true にすると、 ExhangeRateDialog では変化しないようです。誰かが私が間違っていることを説明してください。

為替レート入力

import { composeWithTracker, composeAll } from 'react-komposer';
import React from 'react';
import useContext from '../../../containers/useContext.jsx';
import ExchangeRateValueInput from './ExchangeRateValueInput.jsx';
import ExchangeRateDialog from '../dialogs/ExchangeRateDialog.jsx';

const composer = (props, onData) => {
  onData(null, {});
};

export class ExchangeRateInput extends React.Component { //Wrapper Component
  constructor(props) {
    super(props);
    this.state = {
      value: props.value || '',
      date: '',
      showDialog: props.showDialog || false,
    };
    this.onChange = this.onChange.bind(this);
  }

  onChange(event) {
    const value = event.target.value;

    this.setState({ value });
  }

  onOpenDialog() {
    let bool = true;
    this.setState({ showDialog: bool }, () => {
      console.log(this.state);
    });
  }

  render() {
    return (
      <div>
        <ExchangeRateValueInput onChange={this.onChange} openDialog={this.onOpenDialog.bind(this)} value={this.state.value} />
        <ExchangeRateDialog onChange={this.onChange} open={this.state.showDialog} />
      </div>
    );
  }
}

ExchangeRateInput.propTypes = {
  value: React.PropTypes.number,
  onChange: React.PropTypes.func,
  openExhangeRateDialog: React.PropTypes.func,
};

const ComposedExchangeRateInput = composeAll(
  composeWithTracker(composer),
  useContext()
)(ExchangeRateInput);

export default ExchangeRateInput;

為替レート ダイアログ

import React from 'react';
import FlatButton from 'material-ui/FlatButton';
import DatePicker from 'material-ui/DatePicker';
import Dialog from 'material-ui/Dialog';
import useContext from '../../../containers/useContext.jsx';

export class ExchangeRateDialog extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: '',
      date: '',
      open: props.open || false,
    };
    this.onDialogConfirm = this.onDialogConfirm.bind(this);
    this.onDateChange = this.onDateChange.bind(this);
  }

  onDateChange(date) {
    const value = this.getFakeExchangeRate(); // Replace functionallity with Meteor-method
    setTimeout(() => {
      this.setState({ date, value });
    }, 1100);
  }

  onDialogConfirm() {
    this.props.onDialogConfirm({
      value: this.state.value,
      date: this.state.date,
    });
  }

  getFakeExchangeRate() {
    return Math.random(1, 15);
  }

  actions() {
    return [
      <FlatButton
        label="Cancel"
        secondary
        onTouchTap={this.props.onDialogCancel}
      />,
      <FlatButton
        label="Ok"
        primary
        onTouchTap={this.onDialogConfirm}
        disabled={!this.state.value}
      />,
    ];
  }

  render() {
    return (
      <div >
        <Dialog
          title="Get exchange rate from Riksbanken"
          modal={false}
          open={this.state.open}
          actions={this.actions()}
          onRequestClose={this.props.onDialogCancel}
        >
            Choose a date.
          <div className="layout horizontal">
            <div className="flex">
              <DatePicker
                hintText="No date selected"
                onChange={(event, date) => this.onDateChange(date)}
                maxDate={new Date()}
              />
            </div>
            <div className="flex">
              <h3>{this.state.value ? `Exchange rate: ${this.state.value}` : null}</h3>
            </div>
          </div>
        </Dialog>
      </div>
    );
  }
}

ExchangeRateDialog.propTypes = {
  value: React.PropTypes.number,
  date: React.PropTypes.string,
  open: React.PropTypes.bool,
  onChange: React.PropTypes.func,
  onDialogCancel: React.PropTypes.func,
  onDialogConfirm: React.PropTypes.func,
};

export default ExchangeRateDialog;

為替レート値入力

import React from 'react';
import TextField from 'material-ui/TextField';
import IconButton from 'material-ui/IconButton';
import useContext from '../../../containers/useContext.jsx';

export class ExchangeRateValueInput extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: props.value || '',
      errorMessage: '',
    };
    this.onValueChange = this.onValueChange.bind(this);
  }

  onValueChange(event) {
    const value = event.target.value;
    let errorMessage = '';
    let returnValue = value;

    const isNumber = !isNaN(value); // TODO: Improve validation

    if (!isNumber) {
      errorMessage = 'Must be a number';
      returnValue = '';
    }

    this.setState({
      value,
      errorMessage,
    }, () => {
      this.props.onChange(returnValue);
    });
  }

  onOpenDialog() {
    console.log('hej');
    console.log(this.props);
    this.props.onOpenDialog;
  }

  style = {
    height: 72,
  };

  render() {
    return (
      <div className="layout horizontal" style={this.style}>
        <div
          className=""
        >
          <TextField
            floatingLabelText="Value"
            onChange={this.onValueChange}
            errorText={this.state.errorMessage}
            value={this.state.value}
          />
        </div>
        <div
          className="layout center layout horizontal"
        >
          <IconButton
            className="flex"
            tooltip="Get from Riksbanken"
            onClick={() => this.props.openDialog()}
          >
            <i className="material-icons">search</i>
          </IconButton>
        </div>
      </div>
    );
  }
}

ExchangeRateValueInput.propTypes = {
  value: React.PropTypes.number,
  onChange: React.PropTypes.func,
  openDialog: React.PropTypes.func,
};

export default ExchangeRateValueInput;
4

1 に答える 1

1

valueからExchangeRateInputに渡してExchangeRateValueInputいますが、 の内部状態に格納していますExchangeRateValueInput。この時点で、 から完全に切断されExchangeRateInputます。そのため、ExchangeRateValueInputその状態を更新すると、その親はそれについて何も知りません。

ExchangeRateInputすべての状態がルート コンポーネント ( ) で管理され、その状態が、自身の内部状態ではなく props のみを参照する子に渡されるように書き直すことができます。次に、子が状態を更新する必要がある場合、定義したイベント (たとえばthis.props.onChange、または何か) を呼び出すことができます。ExchangeRateInputこれらのイベントを処理し、それに応じてその状態を更新します。

または、フラックス パターンの使用を検討する必要があります (たとえば、Redux などの使用)。

于 2016-10-21T15:04:17.400 に答える