redux学习理解01

redux-study

Posted by EWL on December 13, 2018

redux的学习实现第一课:理解dispatch对于状态控制的影响

首先,使用create-react-app创建一个新的react项目,将public中的Index.html改为如下结构:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="theme-color" content="#000000">
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
    <title>React App</title>
  </head>
  <body>
  <div id="title"></div>
  <div id="content"></div>
  </body>
</html>

将index.js中的内容删除,并写入如下内容:

let appState = {
  title: {
    text: '我是标题',
    color: 'red'
  },
  content: {
    text: '我是内容',
    color: 'blue'
  }
};

function renderTitle(title) {
  const titleDOM = document.getElementById('title');
  titleDOM.innerHTML = title.text;
  titleDOM.style.color = title.color;
}

function renderContent(content) {
  const contentDOM = document.getElementById('content');
  contentDOM.innerHTML = content.text;
  contentDOM.style.color = content.color;
}

function renderApp(state) {
  renderTitle(state.title);
  renderContent(state.content);
}

renderApp(appState);

此时,使用yarn start启动项目,可以在浏览器中看到如下内容: img.png

问题出现了 此时,我们需要的样式和文本都已经满足需要,但是很明显,这样对于state的直接操作是非常危险的,在renderApp之前可能会有非常多的对于state的操作甚至修改,我们都将其接受了,这对于之后debug是十分不友好的。那么我们需要做的就是尽力避免直接对state修改

所以,在react小书中有这么一段话:

让我们来想办法解决这个问题,我们可以学习 React.js 团队的做法,把事情搞复杂一些,提高数据修改的门槛:模块(组件)之间可以共享数据,也可以改数据。但是我们约定,这个数据并不能直接改,你只能执行某些我允许的某些修改,而且你修改的必须大张旗鼓地告诉我。

如何实现呢?在index.js中添加如下代码:

function dispatch(action) {
  switch (action.type) {
    case 'CHANGE_TITLE':
      appState.title.text = action.text;
      break;
    case 'CHANGE_TITLE_COLOR':
      appState.title.color = action.color;
      break;
    case  'CHANGE_CONTENT':
      appState.content.text = action.text;
      break;
    case 'CHANGE_CONTENT_COLOR':
      appState.content.color = action.color;
      break;
    default:
      break
  }
}

关注点:

  1. 需要借助固定的action.type才能修改唯一对应的功能
  2. 且不借助dispatch就无法更改state的内容

此时,我们通过dispatch对内容做一些修改

function dispatch(action) {
  switch (action.type) {
    case 'CHANGE_TITLE':
      appState.title.text = action.text;
      break;
    case 'CHANGE_TITLE_COLOR':
      appState.title.color = action.color;
      break;
    case  'CHANGE_CONTENT':
      appState.content.text = action.text;
      break;
    case 'CHANGE_CONTENT_COLOR':
      appState.content.color = action.color;
      break;
    default:
      break
  }
}

dispatch({ type: 'CHANGE_TITLE_COLOR', color: 'purple' });
dispatch({ type: 'CHANGE_CONTENT', text: 'content第一次被修改' });
renderApp(appState);

image.png

界面内容成功被修改,即使我们像下面这样在renderApp之前对appState进行魔改,都没有关系,因为我们每一次的修改都是通过dispatch进行的,修改都是可控的,这对于debug来说就更为友好。 原来的修改关系如同下图: img.png 而是用了dispacth的修改关系就多了一层修改控制层: img.png

总而言之,就是多个箭头的修改指向一个appState的情况改为了单个箭头的修改指向appState。 此次的完整代码,如下:

let appState = {
  title: {
    text: '我是标题',
    color: 'red'
  },
  content: {
    text: '我是内容',
    color: 'blue'
  }
};

function renderTitle(title) {
  const titleDOM = document.getElementById('title');
  titleDOM.innerHTML = title.text;
  titleDOM.style.color = title.color;
}

function renderContent(content) {
  const contentDOM = document.getElementById('content');
  contentDOM.innerHTML = content.text;
  contentDOM.style.color = content.color;
}

function renderApp(state) {
  renderTitle(state.title);
  renderContent(state.content);
}

function dispatch(action) {
  switch (action.type) {
    case 'CHANGE_TITLE':
      appState.title.text = action.text;
      break;
    case 'CHANGE_TITLE_COLOR':
      appState.title.color = action.color;
      break;
    case  'CHANGE_CONTENT':
      appState.content.text = action.text;
      break;
    case 'CHANGE_CONTENT_COLOR':
      appState.content.color = action.color;
      break;
    default:
      break
  }
}

dispatch({ type: 'CHANGE_TITLE_COLOR', color: 'purple' });
dispatch({ type: 'CHANGE_CONTENT', text: 'content第一次被修改' });
renderApp(appState);