Состояние Redux для замены внутреннего состояния компонента React - PullRequest
0 голосов
/ 20 января 2020

Я бы хотел создать магазин с избыточностью в нескольких компонентах моего веб-приложения. По сути, я хочу перевести то, что в настоящее время является внутренним состоянием, на приставку.

В качестве примера я использую простое радио.

Файл без приведения (только внутреннее состояние):

// file Bool.js

import React from 'react';
import {FormControlLabel, Grid, Radio, RadioGroup} from "@material-ui/core";

class Bool extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      bool: 'and'
    };
    this.handleChange = this.handleChange.bind(this)
  }

  handleChange = (evt) => {
    this.setState({
      bool: evt.target.value
    });
  }

  render() {
    return(
      <div>

      <RadioGroup
        row
        value={this.state.bool}
        onChange={this.handleChange}>

      <Grid
        container
        direction="row"
        justify="center"
        alignItems="center">
      <FormControlLabel
        value="and"
        control={<Radio
          color="primary"/>}
        label="And"
        labelPlacement="end"/>
      <FormControlLabel
        value="or"
        control={<Radio
          color="primary"/>}
        label="Or"
        labelPlacement="end"/>
      </Grid>
      </RadioGroup>

      </div>
    )
  };
}

export default Bool

Файл с добавлением:

// file Bool.js

import React from 'react';
import {connect} from 'react-redux';
import {FormControlLabel, Grid, Radio, RadioGroup} from "@material-ui/core";
import {handleBool} from './Action_bool'

export class Bool extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      bool: 'and'
    };
    this.handleBool = this.handleBool.bind(this)
  }

  render() {
    return(
      <div>

      <RadioGroup
        row
        value={this.state.bool}
        onChange={this.handleBool}>

      <Grid
        container
        direction="row"
        justify="center"
        alignItems="center">
      <FormControlLabel
        value="and"
        control={<Radio
          color="primary"/>}
        label="And"
        labelPlacement="end"/>
      <FormControlLabel
        value="or"
        control={<Radio
          color="primary"/>}
        label="Or"
        labelPlacement="end"/>
      </Grid>
      </RadioGroup>

      </div>
    )
  };
}

function mapStateToProps(state) {
  return {
    bool: state
  }
}

export default connect(mapStateToProps, {handleBool})(Bool);

Действие:

// file Action_bool.js

export function handleBool(value) {
  return ({
    type: 'HANDLE_BOOL_CHANGE',
    payload: value
  });
}

Редуктор:

// file Reducer_bool

const Reducer_bool = (state = 0, action) => {
  switch(action.type) {
    case 'HANDLE_BOOL_CHANGE':
      return action.payload;
    default:
      return state;
  }
};

export default Reducer_bool

Комбинированные редукторы:

// file Combine_reducers

import {combineReducers} from 'redux';
import Reducer_bool from './Reducer_bool';

export default combineReducers({
  bool: Reducer_bool
});

Индексный файл:

// file index.js

import React from 'react';
import ReactDOM from "react-dom";
import {createStore} from 'redux'
import {Provider} from 'react-redux'
import {Box, CssBaseline, MuiThemeProvider} from "@material-ui/core";
import theme from './Standalone/theme';
import Bool from './Standalone/Bool';
import combineReducers from './Reducer_bool'

let store = createStore(combineReducers)

ReactDOM.render (
  <Provider
    store={store}>
  <MuiThemeProvider
    theme={theme}>
  <CssBaseline/>
  <Bool/>
  </MuiThemeProvider>
  </Provider>,
  document.querySelector("#root")
  )

Ошибка:

Ошибка типа: невозможно прочитать свойство 'bind' из неопределенного

10 |    this.state = {
11 |      bool: 'and'
12 |    };
13 |    this.handleBool = this.handleBool.bind(this)
| ^  14 |  }

Ответы [ 2 ]

0 голосов
/ 20 января 2020

this в строке, из которой исходит ваша ошибка, - поиск функции в контексте текущего класса. Поскольку у класса нет функции handleBool, ни один не будет this, и он не будет определен.

Как уже сказано в ответе @ jank, вам нужно использовать handleBool, присутствующий в this.props. connect автоматически связал ее с функцией диспетчеризации и добавил ее в ваш реквизитный объект.

Полностью удалите эту строку this.handleBool= this.handleBool.bind(this).

И вы можете добавить локальную функцию, подобную этой, чтобы onChange={this.handleBool} будет работать как положено.

handleBool= (evt) => {
  this.props.handleBool(evt.target.value);
}
0 голосов
/ 20 января 2020

Вы можете отменить привязку к handleBool в конструкторе

Вместо этого используйте функцию стрелки в атрибуте onChange:

<RadioGroup
        row
        value={this.state.bool}
        onChange={({ value })) => this.props.handleBool(value)}> // this is the action from redux
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...