是否可以在 Redux/React 中分离组件的表示和逻辑?

IT技术 reactjs redux
2021-04-27 18:43:03

如 redux -> https://redux.js.org/basics/usage-with-react 的官方文档所示,逻辑和预设必须捆绑在一起。

问题是 - 我们不能将它们分开以使我们的代码更清晰,这是真的吗?

例如来自官方 redux.js.org 文档的一些组件。所以,逻辑和预制放在一起,看起来不太好和清晰:

import React from 'react'
import { connect } from 'react-redux'
import { addTodo } from '../actions'
 
let AddTodo = ({ dispatch }) => {
  let input
 
  return (
    <div>
      <form
        onSubmit={e => {
          e.preventDefault()
          if (!input.value.trim()) {
            return
          }
          dispatch(addTodo(input.value))
          input.value = ''
        }}
      >
        <input
          ref={node => {
            input = node
          }}
        />
        <button type="submit">
          Add Todo
        </button>
      </form>
    </div>
  )
}
AddTodo = connect()(AddTodo)
 
export default AddTodo

PS我也看到了这个问题:Separatingpresentational and logic components react/redux,这不一样。

UPD:我将逻辑分为 onSubmit module和组件呈现。但是 > 现在我收到一个错误 - TypeError: Cannot call a class as a function

/* 推介会 */

import React from 'react';
import { connect } from 'react-redux';
import AddTodo from '../../Actions/AddTodo'
import addTodo from '../../Modules/handleClick'

class AddTodos extends React.Component{    
    componentDidMount() {
        console.log(addTodo()); // for test. Get "TypeError: Cannot call a class as a function"
    }

    render() {
        return (
            <form>
                <input type="text" placeholder="Your text" />
                <button type="submit">Add todos</button>
            </form>
        );  
    }
}

export default AddTodos;

/* 提交module */

import { connect } from 'react-redux';
import AddTodo from '../Actions/AddTodo'

let addTodo = ({ dispatch }) => {
    if (document.readyState === 'complete') {
        let form = document.querySelector('form');
        form.addEventListener('submit', handleClick);

        function handleClick(e) {
            e.preventDefault();

            let input = document.querySelector('input');    
            dispatch(AddTodo(input.value));

            input.value = '';
        }
    }
}

addTodo = connect()(addTodo);

export default addTodo;
1个回答

从您提供的同一文档中:

有时很难判断某个组件应该是展示组件还是容器。例如,有时形式和功能确实是耦合在一起的,例如在这个微小的组件的情况下:

AddTodo is an input field with an “Add” button

从技术上讲,我们可以将其分为两个部分,但现阶段可能还为时过早在一个非常小的组件中混合表示和逻辑是很好的。随着它的增长,如何拆分它会更加明显,因此我们将其混合。

所以是的,您是对的,最好将我们的展示组件和容器组件分开,并且正如您所说的那样,在文档中对此进行了很好的解释。你举的例子只是一个例外。

在这里你可以如何分离组件:

添加待办事项

import React from "react";
import PropTypes from "prop-types";
import { connect } from "react-redux";
import { addTodo } from "../actions";
import AddTodoForm from "./AddTodoForm";

const AddTodo = ( props ) => {
    const handleAddTodo = todo => props.dispatch( addTodo( todo ) );

    return (
        <AddTodoForm addTodo={handleAddTodo} />
    );
};

export default connect()( AddTodo );

添加TodoForm

import React from "react";

const AddTodoForm = ( props ) => {
    let input;

    const handleClick = () => {
        props.addTodo( input.value );
        input.value = "";
    };


    return (
        <div>
            <input
                ref={( node ) => {
                    input = node;
                }}
            />
            <button
                onClick={handleClick}
            >
    Add Todo
            </button>
        </div>
    );
};

export default AddTodoForm;

我强烈建议您观看 Dan Abramov(Redux 的创建者)在 Egghead 上的 Redux 视频。看完这些视频,你就会从头了解 Redux 的逻辑。有两部分,两部分都看。在我学习 Redux 时,我观看了这些并在观看的同时编写了所有代码。之后我创建了一个仓库:https : //github.com/devserkan/react-with-idiomatic-redux

你可以克隆这个 repo 并随意玩。