首页 > 解决方案 > React Redux 不更新文本输入 onChange

问题描述

我见过类似的问题,但它们似乎没有帮助。我有一个正在实施 redux 的 React 项目。

我的 index.js 如下:

import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
import { createStore } from "redux";
import { Provider } from "react-redux";

import reducer from "./store/reducer";

import "./index.css";
import App from "./App";
import * as serviceWorker from "./serviceWorker";

const store = createStore(reducer);

const app = (
  <Provider store={store}>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </Provider>
);

ReactDOM.render(app, document.getElementById("root"));

serviceWorker.unregister();

我的 reducer.js 是这样的:

import * as actionTypes from "./actions";

const initialState = {
  searchValue: "",
  finalSearchValue: ""
};

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case actionTypes.UPDATE_INPUT_VALUE:
      return {
        searchValue: state.searchValue
      };
    case actionTypes.SUBMIT_QUERY:
      return {
        finalSearchValue: state.finalSearchValue
      };
    default:
      return state;
  }
};

export default reducer;

而我的 Songfinder.js - 我正在尝试 mapStateToProps 和 mapDispatchToProps 的地方是这样的:

import React, { Component } from "react";
import { connect } from "react-redux";
import PanelSearchResults from "../../components/PanelSearchResults/PanelSearchResults";
import Playlist from "../Playlist/Playlist";

import classes from "./SongFinder.css";
import Auxilliary from "../../hoc/Auxilliary";
import * as actionTypes from "../../store/actions";

class SongFinder extends Component {
  props: {
    searchValue: string;
    finalSearchValue: string;
  };

  componentDidMount() {
    console.log(this.props);
  }

  updateInputValue(evt) {
    this.props.onUpdateSearchValue(evt.target.value);
  }

  onSubmitQueryHandler() {}

  render() {
    if (this.props) {
      return (
        <Auxilliary>
          <div className={classes.panel}>
            <input
              className="searchBox"
              type="text"
              value={this.props.searchValue}
              onChange={evt => this.updateInputValue(evt)}
            />
            <button type="submit" onClick={this.onSubmitQueryHandler}>
              Submit
            </button>
          </div>
          <div className={classes.panel}>
            <h1>Playlist</h1>
            <Playlist />
          </div>
          <PanelSearchResults search={this.props.finalSearchValue} />
        </Auxilliary>
      );
    } else {
      return null;
    }
  }
}

const mapStateToProps = state => {
  return {
    searchValue: state.searchValue,
    finalSearchValue: state.finalSearchValue
  };
};

const mapDispatchToProps = dispatch => {
  return {
    onUpdateSearchValue: value =>
      dispatch({
        type: actionTypes.UPDATE_INPUT_VALUE,
        searchValue: value
      }),
    onSubmitQuery: value =>
      dispatch({
        type: actionTypes.SUBMIT_QUERY,
        finalSearchValue: value
      })
  };
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(SongFinder);

每次更改输入文本时,我希望通过 mapDispatchToProps 更新状态,并且我希望 onChange 事件触发 updateInputValue 处理程序,该处理程序应该触发 mapDispatchToProps 中的 onUpdateSearchValue,并将其发送 evt.target.value。

撕扯我的头发试图弄清楚为什么它不起作用。我在 React 16.6.3 - 是打字稿错误吗?我在 reducer 中声明的 initialState 中的两个值都通过 Songfinder.js 中的 componentDidMount() 记录到控制台,因此该组件可以使用道具吗?

标签: reactjstypescriptreduxreact-redux

解决方案


看起来你的问题是减速器实际上并没有创建任何新状态,因为你指的是state而不是action在派生新状态时。该state参数包含上次运行 reducer 时的先前状态,而action包含这次派生新状态所需的信息。像这样:

import * as actionTypes from "./actions";

const initialState = {
  searchValue: "",
  finalSearchValue: ""
};

const reducer = (state = initialState, action) => {
  switch (action.type) {
    case actionTypes.UPDATE_INPUT_VALUE:
      return {
        searchValue: action.searchValue,
        finalSearchValue: ""
      };
    case actionTypes.SUBMIT_QUERY:
      return {
        searchValue: "",
        finalSearchValue: action.finalSearchValue
      };
    default:
      return state;
  }
};

export default reducer;

我还在上面的返回中添加了额外的字段,因为 reducer 可能每次都应该返回一个完整的状态(与 相同的形状initialState)。


推荐阅读