【问题标题】:Default value for Redux-thunk inputRedux-thunk 输入的默认值
【发布时间】:2019-01-06 15:23:44
【问题描述】:

我有一个带有 thunk 的简单 SPA。它使用 github API 来获取 repos 列表。 我以前有一个带有类表示组件的示例。它有一个本地状态,但我决定尽可能简化示例并将其重构为功能并删除本地状态并使用 ref 获取输入值。效果很好

  1. 如何在输入字段中设置默认值,以便在应用加载时获取该值。
  2. 我不太明白如何删除 combineReducers 并使用单个 reducer,就像我使用带有单个 reducer 应用程序中断的 createStore 时一样

代码如下: https://codesandbox.io/s/k13nowrj33

import React, { Component } from "react";
import ReactDOM from "react-dom";
import { applyMiddleware, combineReducers, createStore } from "redux";
import { connect, Provider } from "react-redux";
import thunk from "redux-thunk";
import "./index.css";

// actions.js
const addRepos = repos => ({ type: "ADD_REPOS", repos });
const clearRepos = () => ({ type: "CLEAR_REPOS" });
const getRepos = username => async dispatch => {
  try {
    const url = `https://api.github.com/users/${username}/repos`;
    const response = await fetch(url);
    const responseBody = await response.json();
    dispatch(addRepos(responseBody));
  } catch (error) {
    console.log(error);
    dispatch(clearRepos());
  }
};

// reducers.js
const repos = (state = [], action) => {
  switch (action.type) {
    case "ADD_REPOS":
      return action.repos;
    case "CLEAR_REPOS":
      return [];
    default:
      return state;
  }
};

const rootreducer = combineReducers({ repos });

const store = createStore(rootreducer, applyMiddleware(thunk));

// App.js
function App(props) {
  var textInput;
  var setTextInputRef = element => { textInput = element; };
  var submit = () => props.getRepos(textInput.value);
  return (
    <div>
      <h1>Github username: </h1>
      <input type="text" ref={setTextInputRef} />
      <button onClick={submit}>Get All Repos</button>
      <ul>
        {props.repos.map((repo, index) => (<li key={index}><a href={repo.html_url}>{repo.name}</a></li> ))}
      </ul>
    </div>
  );
}

// AppContainer.js
const mapStateToProps = state => ({ repos: state.repos });
const mapDispatchToProps = { getRepos };
const AppContainer = connect(mapStateToProps, mapDispatchToProps)(App);

ReactDOM.render(<Provider store={store}><AppContainer /></Provider>, document.getElementById("root"));

【问题讨论】:

  • 默认输入值是什么意思?
  • 任何像字符串一样的 github 用户名。例如 - mapledrive
  • “应用中断”是什么意思。究竟会发生什么?如果您不使用combineReducers,您的存储状态将具有不同的形状,因此您还必须更改mapStateToProps 函数。似乎您可能希望将整个状态作为道具传递。 const mapStateToProps = state =&gt; state.
  • 当我写 const store = createStore(repos, applyMiddleware(thunk)); typeerror 告诉 props.repos 未定义
  • 是的。所以检查堆栈跟踪。如果您希望将整个状态作为称为 repos 的 prop 传递,您可以使用 mapStateToProps = state =&gt; ({repos: state})

标签: reactjs redux react-redux redux-thunk


【解决方案1】:

1.) 您可以为此目的使用defaultValue

2.) 如 cmets 中所述,如果您不使用 combineReducers(),则需要更改您的 mapStateToProps()

这是一种方法:

import React, { Component } from "react";
import ReactDOM from "react-dom";
import { applyMiddleware, combineReducers, createStore } from "redux";
import { connect, Provider } from "react-redux";
import thunk from "redux-thunk";
import "./index.css";

// actions.js
const addRepos = repos => ({ type: "ADD_REPOS", repos });
const clearRepos = () => ({ type: "CLEAR_REPOS" });
const getRepos = username => async dispatch => {
  try {
    const url = `https://api.github.com/users/${username}/repos`;
    const response = await fetch(url);
    const responseBody = await response.json();
    dispatch(addRepos(responseBody));
  } catch (error) {
    console.log(error);
    dispatch(clearRepos());
  }
};

// reducers.js
const repos = (state = [], action) => {
  switch (action.type) {
    case "ADD_REPOS":
      return action.repos;
    case "CLEAR_REPOS":
      return [];
    default:
      return state;
  }
};

const store = createStore(repos, applyMiddleware(thunk));

// App.js
function App(props) {
  var textInput;
  var setTextInputRef = element => {
    textInput = element;
  };
  var submit = () => props.getRepos(textInput.value);
  return (
    <div>
      <h1>Github username: </h1>
      <input defaultValue="colinricardo" type="text" ref={setTextInputRef} />
      <button onClick={submit}>Get All Repos</button>
      <ul>
        {props.repos.map((repo, index) => (
          <li key={index}>
            <a href={repo.html_url}>{repo.name}</a>
          </li>
        ))}
      </ul>
    </div>
  );
}

// AppContainer.js
const mapStateToProps = state => ({ repos: state });

const mapDispatchToProps = { getRepos };
const AppContainer = connect(
  mapStateToProps,
  mapDispatchToProps
)(App);

ReactDOM.render(
  <Provider store={store}>
    <AppContainer />
  </Provider>,
  document.getElementById("root")
);

代码沙盒here.

在加载时获取 repos:

import React, { Component } from "react";
import ReactDOM from "react-dom";
import { applyMiddleware, combineReducers, createStore } from "redux";
import { connect, Provider } from "react-redux";
import thunk from "redux-thunk";
import "./index.css";

// actions.js
const addRepos = repos => ({ type: "ADD_REPOS", repos });
const clearRepos = () => ({ type: "CLEAR_REPOS" });
const getRepos = username => async dispatch => {
  try {
    const url = `https://api.github.com/users/${username}/repos`;
    const response = await fetch(url);
    const responseBody = await response.json();
    dispatch(addRepos(responseBody));
  } catch (error) {
    console.log(error);
    dispatch(clearRepos());
  }
};

// reducers.js
const repos = (state = [], action) => {
  switch (action.type) {
    case "ADD_REPOS":
      return action.repos;
    case "CLEAR_REPOS":
      return [];
    default:
      return state;
  }
};

const store = createStore(repos, applyMiddleware(thunk));

// App.js
class App extends React.Component {
  componentDidMount() {
    this.submit();
  }

  submit = () => this.props.getRepos(this.textInput.value);

  render() {
    return (
      <div>
        <h1>Github username: </h1>
        <input
          defaultValue="colinricardo"
          type="text"
          ref={ref => (this.textInput = ref)}
        />
        <button onClick={this.submit}>Get All Repos</button>
        <ul>
          {this.props.repos.map((repo, index) => (
            <li key={index}>
              <a href={repo.html_url}>{repo.name}</a>
            </li>
          ))}
        </ul>
      </div>
    );
  }
}
// AppContainer.js
const mapStateToProps = state => ({ repos: state });

const mapDispatchToProps = { getRepos };
const AppContainer = connect(
  mapStateToProps,
  mapDispatchToProps
)(App);

ReactDOM.render(
  <Provider store={store}>
    <AppContainer />
  </Provider>,
  document.getElementById("root")
);

【讨论】:

  • 我试过了,它在输入中显示默认值。可惜它没有使用 repos 列表设置状态,因此在加载应用程序后应用程序不会呈现 repos 列表
  • 我认为您正在获取缓存版本。在隐身模式下试试吧!
  • 我试过了。我认为应用加载时应该有一些默认操作发送到减速器
  • 哦,我的错 - 你的意思是在应用加载时已经加载了它们。您只需更改为类组件并在componentDidMount() 中运行submit()。编辑:我已将此代码添加到答案中,CodeSandbox 在这里:codesandbox.io/s/y20x70l7x9
  • 上课很简单。如何用功能制作它。我最初是从课堂开始的,并且有本地状态。所以我决定简化它。我的想法是将所有逻辑保留在表示组件之外。所以你的例子很棒,但它使用了类组件
猜你喜欢
  • 1970-01-01
  • 2016-04-25
  • 1970-01-01
  • 1970-01-01
  • 2017-09-23
  • 2017-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多