无法将mapStateToProps连接到React组件

时间:2020-05-14 00:46:32

标签: reactjs typescript redux react-redux

我是React + Redux的新手,正在构建一个Todo应用程序。

类型“ {}”中缺少属性“待办事项”,但类型“ { 待办事项:Todo []; }'。 TS2741

我认为问题是我无法连接(反应-redux)状态到TodoList。我可以确认这一点,因为我从<TodoList />跳转到其功能组件connect(mapStateToProps)(TodoList),而不是connect(mapStateToProps)(TodoList)

CodeSandbox:https://codesandbox.io/s/flamboyant-dream-w7drj?file=/src/App.tsx:712-713

我已经阅读了react-redux文档,但没有找到解决方法。

代码:

import React, { useState } from 'react';
import { connect } from 'react-redux'
import { addTodo} from './index'

function AddToDo() {
  const [input, setInput] = useState('')

  function handleInput(e: React.ChangeEvent<HTMLInputElement>) {
    setInput(e.target.value)
  }

  //dispatch to store
  function handleAddTodo() {
    addTodo(input)
    setInput('')
  }

  return (
    <div>
      <input type="text" onChange={(e) => handleInput(e)}/>
      <button type="button" onClick={handleAddTodo}>
        Add todo
      </button>
    </div>
)
}

//connect
connect(null, { addTodo })(AddToDo)

//TodoList
interface Todo {
  id: number
  text: string
}

interface TodoState {
  todos: Todo[]
}

function TodoList({ todos}:{ todos: Todo[]}) {

  return (
    <ul className="todo-list">
      {todos.map((todo: Todo, index) => {
        return <Todo todo={todo} />;
        })
       }
    </ul>
  )
}

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

connect(mapStateToProps)(TodoList)

//Todo
function Todo({ todo }: { todo: Todo }) {

  return (
    <li>
      {todo}
    </li>
  )
}

function App() {
  return (
    <div className="App">
      <AddToDo />
      <TodoList /> <---------------------- Error info: Property 'todos' is missing in type '{}' but required in type '{ todos: Todo[]; }'.  TS2741
      </div>
  );
}

export default App;

2 个答案:

答案 0 :(得分:1)

根据您的codeandbox示例,我注意到了一些问题。

TLDR-here's a working example using your code with some modifications

让我们逐步介绍每个组件。


index.tsx

const todoApp = combineReducers({
  todoReducer
});

应更改为:

const todoApp = combineReducers({
  todos: todoReducer
});

原因: 您的整个应用是在您通过state.todos访问待办事项的前提下进行的。如果您将代码保留为原来的样子,则必须访问state.todoReducer


AddToDo

function AddToDo() {
  const [input, setInput] = useState('')

  function handleInput(e: React.ChangeEvent<HTMLInputElement>) {
    setInput(e.target.value)
  }

  //dispatch to store
  function handleAddTodo() {
    addTodo(input)
    setInput('')
  }

  return (
    <div>
      <input type="text" onChange={(e) => handleInput(e)}/>
      <button type="button" onClick={handleAddTodo}>
        Add todo
      </button>
    </div>
)
}

应更改为:

const addToDoConnector = connect(null, { addTodo });
// store the connect function so it can be used in typings and to create component
const ConnectedTodo = addToDoConnector(AddToDo);

function AddToDo(props: ConnectedProps<typeof addToDoConnector>) {
  const [input, setInput] = useState('')

  function handleInput(e: React.ChangeEvent<HTMLInputElement>) {
    setInput(e.target.value)
  }

  //dispatch to store
  function handleAddTodo() {
    props.addTodo(input)
    setInput('')
  }

  return (
    <div>
      <input type="text" onChange={(e) => handleInput(e)}/>
      <button type="button" onClick={handleAddTodo}>
        Add todo
      </button>
    </div>
)
}

原因: 您正在文件顶部导入名为addTodo的变量。我们需要访问AddToDo组件的addTodo属性,以便将其调度到商店。


TodoList:

function TodoList({ todos}:{ todos: Todo[]}) {

  return (
    <ul className="todo-list">
      {todos.map((todo: Todo, index) => {
        return <Todo todo={todo} />;
        })
       }
    </ul>
  )
}

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

connect(mapStateToProps)(TodoList)

应更改为:

// store the connect function so it can be used in typings and to create component
const todoListConnector = connect(mapStateToProps);
const ConnectedTodoList = todoListConnector(TodoList);

function TodoList({todos}: ConnectedProps<typeof todoListConnector>) {
  return (
    <ul className="todo-list">
      {todos.map((todo: Todo, index) => {
        return <Todo todo={todo} />;
        })
       }
    </ul>
  )
}

function mapStateToProps(state:TodoState) {
  return state;
}

原因: 您的mapStateToProps将状态包装在名为state的属性中。也就是说,如果您的状态为{todos: []},则将其更改为{state: { todos: [] } }


Todo

//Todo
function Todo({ todo }: { todo: Todo }) {

  return (
    <li>
      {todo}
    </li>
  )
}

应更改为:

//Todo
function Todo({ todo }: { todo: Todo }) {
  return <li>{todo.text}</li>;
}

原因:

Todo是一个对象。我们想要渲染对象的文本。


App

function App() {
  return (
    <div className="App">
      <AddToDo />
      <TodoList />
      </div>
  );
}

应更改为:

function App() {
  return (
    <div className="App">
      <ConnectedTodo />
      <ConnectedTodoList />
      </div>
  );
}

原因: 调用connect不会更改基础组件。您需要将该值存储在变量中或具有专用文件并export


让我知道您是否还有其他问题。编码愉快。

答案 1 :(得分:-1)

检查此处的工作示例,进行一些修改 CodeSandbox