foxlele2014 / boring

boring
0 stars 0 forks source link

react+redux的问题。。。 #7

Open foxlele2014 opened 7 years ago

foxlele2014 commented 7 years ago

export default connect(state => state.user, action)(User);

这里的connect的使用, image

它会返回一个函数,要求传component过去,就是user啦。 image

http://www.cnblogs.com/lewis617/p/5145073.html

foxlele2014 commented 7 years ago

遇到一个页面有很多不同的按钮,触发不同的弹窗时,这时对应有很多个不同弹窗的action,包括(关闭和打开共用同一个,有一个状态值,表示开或者关闭),请求数据之类的。

在处理这些action时,是给每个action都bind一下直接传递过去,还是写很多个外层函数来调用(使用箭头函数是不需要bind的)。这种很麻烦,太多了

还有一种是不传action值。直接使用当前状态的反状态。

foxlele2014 commented 7 years ago

Super expression must either be null or a function, not undefined

React.Component将Component写成小写开头了。。。。。

感觉react的意识不强,才导致的。。。。

https://stackoverflow.com/questions/37676522/react-native-super-expression-must-either-be-null-or-a-function-not-undefined

还有将组件名写错了。。。。。如 Components, 莫名奇妙加了个s。。。

foxlele2014 commented 7 years ago

创建组件时,可以有也可以没有,但是有constructor的时候就一定要有super(props){}, 应该可以用来定义属性???,还不太懂。。 constructor(){ super() } }

构造函数,通过super(props)传递props

------------------- 总是不太能分清几时用state好还是用props好-------------------

导致我每次基本都用props= =。

http://www.th7.cn/web/js/201701/210093.shtml

foxlele2014 commented 7 years ago

关于如何使用select。。。。(感觉用react都得用原生方法来获取各种值= =。

这个等会写。(例如设置默认值,defaultValue,获取它都值)

举个栗子: 新建用户,有个公司列表的select(公司列表动态获取), 编辑用户信息时,这个公司列表。。

foxlele2014 commented 7 years ago

父组件和子组件如何传递ref属性。

目前在父组件里使用了ref,子组件也使用了ref, this.refs['company'].refs.company.selectedOptions[0].innerText, 获取值的时候这么麻烦= =。。。。。

有一种方法可以不用那么麻烦= =。但是没理解到是为什么。 研究下= =。

可以这么用: 在父组件的时候写ref的时候不需要写名字, 直接写ref={(select} => this.select = select }, 就是说将子组件的ref值传给父组件。。。

this当前组件才会传给当前组件, this.props

foxlele2014 commented 7 years ago

几时需要使用bind,以及dispatch。

(当函数里需要使用this的时候则需要bind)

本来不用使用dispatch的,但是又重复用了,则会执行两次。reducer的内容。。。。

foxlele2014 commented 7 years ago

虚拟dom

https://github.com/livoras/blog/issues/13

foxlele2014 commented 7 years ago

背景:根据接口返回的路径(一张图片),然后弹出浏览器的打印窗口。

想到的解决方法就是在当前页面用一个iframe来实现。。 (还有另一个方法就是用新页面,但是这会麻烦一点) 因为是基于window.print()的方法,所以可以通过window.frames['name']来获取到对应的iframe,

设置display:none;

用的是react来写的。定义了isPrint和pic的state,

但是这个打印窗口一直出不来。。 使用componentDidUpdate检查isPrint是正确的, 但是获取window.frames['name'].images[0]一直都是undefined

但是在console里输入却是存在的。。

弄了好久,最后发现是图片的原因。。 react里的render是渲染dom而已,dom渲染完成不代表所有的元素都完成了

所以在componentDidUpdate里获取img时,当它还没有完全加载出来图片是获取不到的。

所以在iframe里加了onLoad事件,在这里是判断打印窗口的弹出。。

还有,居然设置iframe的class是无法通过这个class来控制img的大小的 如 .style img{.....}

所以还加上了 window.frames['name'].images[0].setAttribute('style','width:xxx;height:xxx');

然后就顺利解决了。。。 弄了我一天。心好累。。

查了下,发现原来有一部分人也有这种需求。。

而且当你查关键字react onload的时候,

出来的内容基本都是react iframe onload之类的。

----------分割线---------- 本来是可以用特殊字符串来表示当前需要打印的区域的,就可以不用使用iframe了。。。但是因为是jsx的原因,所以不能支持这些特殊字符串。。。。。💔

补下别人的:http://react-china.org/t/topic/6983

foxlele2014 commented 7 years ago

还有一点感觉不太好的,就是你更新了几次State,它都会重新render一遍。。。感觉好烦。。。 虽然可以通过componentShouldUpdate来判断。。但是有些情况下它就是需要这样,因为它里边的每块都是获取了不同的State来拼合而成的。。 所以判断的时候就不知道要怎么判断了。。。 值的研究一下。

----------- 很神奇的一点----------

事实上,seatState是不会每次都立马render的, 但是不知道为什么,是因为使用了其他库的原因,所以导致了它每次都能render。

一般在componentWillReceiveProps里更新state,单但假如这个更新state是一个函数,这个函数并没有使用nextprops,而且使用了this.props,则这个this不是最新的props,

然后有人使用了context(这个则是新的了窝~

foxlele2014 commented 7 years ago

和上上个打印的问题有关系。。同样的在另外一个页面也有弹出打印窗口的功能,也是发送个请求获取到路径,然后修改State的值print:true,以及图片的路径。

但是onLoad调用的函数里,通过 this.props.print来判断的时候,这个print还是旧的不是,当前这个,图片的路径也是空,。。。

这就觉得很奇怪了。

同样都是this.props为什么会不一样呢。 很疑惑。。。💔

然后使用componentWillUpdate这个来检验nextprops,nextProps正是我们需要的那个props。。。这就很迷茫了。。

按道理onLoad的时候是已经使用了nextprops来渲染了dom结构了的。。

所以onLoad函数用的时候,这个this.props应该就是最新的了。。

不明白。。。我问问校友。。

------------ 目前就通过判断这个图片是否已经完全加载来执行window.print操作。 window.frames['name'].images[0]

foxlele2014 commented 6 years ago

感觉写的有些问题好弱智啊 = =。

foxlele2014 commented 6 years ago

背景:一个页面,表格类型,然后有一些新增、删除、编辑之类的操作。

新增这些需要弹窗,然后写了一个新文件。作为子组件。

然后有些做法。其实都可以的。

例如:

  1. 弹窗子组件不做任何操作,只是将父亲传来的各种东西绑定在自己身上。。如input要双向绑定,需要一个state,然后这个state也是父亲那边传过来的props。

之后的添加操作也是父亲的函数,然后父亲获取到对应的值。

  1. 将这些东西都直接写在这个弹窗里边,作为自己的state,然后获取的操作也是自己做,dispatch到服务端的函数可以是用父亲传过来的,也可以是自己去dispatch对应的action。

所以我不太懂这两种做法怎么取舍。

第一种,就是需要弹窗关闭的时候置空之前填写的值,避免下次打开还是之前填写的。 第二种,则不需要,因为每次点击,都是重新渲染出来的。所以state又会初始化一次。

foxlele2014 commented 6 years ago

何时要用redux,虽然说是为了能统一管理数据流。。。 不过写起来的时候,觉得数据流的子项一部分都是每个组件自身自己写入的。 如:表格的数据。

不过的确会好管理一点点,假如输出对不上预期的,就直接查看store的数据是怎么样的,不需要深入到组件里边去。

可以参考这篇文章,感觉写出了为啥要用redux吧

foxlele2014 commented 6 years ago

react写的单页面,然后又不想让别人感觉到你的是单页面。。 不过就有点问题了。 是在componentWillMount的时候才去请求数据, 再次点击当前tab的时候,因为组件没有发生变化,所以不会去请求数据。

然后qa就说这个有问题啊。 不能这个样子啊。我们需要它重新加载一下。

然后说是用store去管理数据。

切换tab的时候,原来页面的tab的各种筛选没有变化。但是展示在页面上的数据却没有恢复展示。 这点也很尬了。

那么我们就切换tab的时候做一次恢复原来页面的数据吧。。

然后这里恢复有两种方法。一种(因为用了dva,所以我写在了subcription里,这里是监听了url变化,然后它重复点击当前tab的时候,数据没更新,但是里边的有些状态变化了。)

另一种是通过componentWillUnmount来恢复。。

通过这么比较,感觉是这个组件销毁的时候恢复比较好


然后又说,因为每个页面里边还有子页面,然后可以返回。

这个时候返回,他其实也会重新初始化组件,各种东西也会变成最初的,

qa和产品们又说,不行啊,子页面里边的返回我们想要保留这些状态啊。。。


然后他们加了个参数给这些子页面。这个参数用来表示是否要恢复还是保留状态。。 然后并读取这个参数在恢复的函数里判断,以便是否要执行他们。。。

但是保留其实也是很大工作量的,因为得还原页面的展示状态。。。。

foxlele2014 commented 6 years ago

编辑功能,然后因为需要用到对应的数据,数据里边有个数组,然后直接将数组用store存起来,之后这个数组传递到子弹窗的时候,对这个数组进行修改,它父亲里的数据项居然会发生改变。因为是采用赋值,而且因为是对象,不是简单数据。所以,他其实还是引用传递而不是值传递。

用的是antd,table渲染的时候是有record的,就是说直接操作这个record,他其实是会修改到原数据的。。。

弹窗里可以添加多条配置,然后假如我们不加配置,只是删除这些配置,但是不保存,然后删完了之后,点取消(就相当于没操作这个数据。)。这时,页面对应的这个配置的展示变成了空。

所以啊,返回来的数据,特别是存在store里只用于展示的数据不要轻易去修改(获取table时存了一次全部的data,然后每条里再取出来,再存了一次。因为都是引用传递而且不是简单数据类型,所以有坑了。


解决方法目前可以对这个数据进行深拷贝一份,或者传过来的时候可以对它JSON.stringify

foxlele2014 commented 6 years ago

背景:react-router 、单页面

需求:重复点击当前导航时,能重新加载页面(重新初始化)

单页面、react、生命周期,因为重新点击导航时,还是处在当前这个页面,没有发生任何生命周期内的事,也没有触发页面所绑定的任何事件。所以没有任何反馈。。。

这时用到了withRouter提供的location。传递到每个component(应该准确的是说子component),

location这个对象有pathname、对应的key,对应history stack里的每个pathname。

push进去的pathname都有唯一的一个key, 然后就在componentWillReceiveProps里写

 //重复点击导航时重新初始化页面
 if(nextProps.location.pathname === this.props.location.pathname && nextProps.location.key !== this.props.location.key) {
 this.getProductList(1,nextProps);
}

用pathname和key来判断是否有重新点击导航。。

发现用dva-loading的时候,它判断是否处于loading时,是通过是否在执行effect的。所以它会修改很多次store,,所以这个componentWillReceiveProps也会执行很多次。。。。

不太懂他是怎么判断effect已经执行完了。。然后置store里的loading为false

foxlele2014 commented 6 years ago

有一点很烦人的是:当你重新初始化时,又得将所有的页面之前的操作痕迹销毁(如排序、筛选、查询之类的),这点很尴尬。每个人写的代码都不一样。

如:都在同一个组件里边写的,然后把这些东西都当成了store里的一部分,而不是自身组件的state。。 这时可以直接操作store里的东西,使用一个reducers来重置。。。

又如: 分成了好几块。如表格是组件里边的子组件,然后组件有自身的state,如整个页面的查询值,表格这个子组件又又自身的filter、sorter、还有page之类的。

这时你要重置这些值,会发现很麻烦,要修改子组件的state,是不是只有通过传递props,然后再在子组件state赋值时,判断是否有对应的props呢?

foxlele2014 commented 6 years ago

那么还有一点:你重置完了之后。发现填写在input框里的值一直还在。这就很烦人了。。。。。。

但是很神奇,明明已经重置了对应的值,因为我们会给他们赋值。。。


不过是在componentDidMount。这个点就很尴尬了。。。因为重新点击导航时,组件是没有销毁的。。。

不过也很神奇。不是写在表格里边的input框的值已经重置了,因为使用的是defaultValue来赋值的,所以因为对应的store值改变了,所以他也重新渲染了。但是。table里的,因为是在componentDidMount里赋值的。所以没有再次执行。这点很尴尬。。。

foxlele2014 commented 6 years ago

感觉还是直接用jsx的方式来写react会容易理解太多了。。。

用对象的方式,即各种东西都写成一个可配置的对象,然后再通过这个可配置的对象循环(这里边有各种处理操作,因为需要处理默认值之类的),得到可以使用在某个组件身上的对象。。

这种就相对比较难理解了。。。

foxlele2014 commented 6 years ago

每种状态都是可以数据化的对象。。发现还是挺复杂的,当你需要还原原来的状态时,还得重新获取到值,之后再写入到组件里边。

虽然很好管理。。。

foxlele2014 commented 6 years ago

遇到个很有意思的问题,之前写弹窗的时候,总是习惯先判断状态是否是打开,是的话就渲染对应的弹窗元素,不是的话就直接是null。

之前觉得没有太多的什么问题,只是习惯而已。

刚刚遇到一个。没有这样的判断直接写了,虽然不会在页面上展示,但是其实这个元素已经渲染了,就是这个元素的react生命周期已经完成到render了。

然后再获取props的时候,没有获取到对应的值,当时就觉得奇怪,其实是因为需要在它点击“编辑”时才会修改对应的数据,然后才能在里边获取到。。

所以假如没有加入状态判断直接渲染的,它点击的时候就是componentReceiveProps了,假如在想再constructor里获取到初始值的时候,就不能按预期了。。

然后因为这个原因。 有个弹窗里的表单,切换类型的时候,因为感觉有部分的描述一致,然后共用了一部分input, 它用是同一个值进行双向绑定。,所以切换类型时,会发现之前填写的部分会出现在刚刚切换的input里边。这时使用的人肯定会有点疑惑。

所以在切换类型的时候,对input进行了清理。

那么编辑的时候呢,因为他也是由判断某个值是否存在,之后才去省城对应的input的,所以切换的时候就会重新render input,所以绑定的值还是会有。所以清理时,是不影响编辑的。。

这时,我记录了打开弹窗时所选的类型,用来判断编辑时所要初始化值的元素是否需要初始值。


感觉写的有点乱,后半部分= =。

foxlele2014 commented 6 years ago

用dva-loading,就相当于是发生了effect就会有loading的状态变化,然后在layout层绑定的这个loading状态。,,,然后有点很尴尬的地方。。。就是弹窗里有autoComplete这种检测input发生了变化就出发一个搜索。。。这时是这个搜索是在一个effect里的。。。。 然后页面就后有两个蒙版。。。。。

完成时,loading的那个蒙版就消失了。。。 感觉。。。好奇怪。。。

foxlele2014 commented 6 years ago

redux 里的store提供了dispatch、subscribe、unsubscribe、以及emit某事件,然后监听某事件。更新data,

emit感觉有点像jq里的trigger,就是去主动触发它,而不是用户去触发它。

foxlele2014 commented 6 years ago

之前看到说在jsx里最好不要写匿名函数。然后bind最好在constructor里写,假如在render里写的话,每次渲染都会重新bind,可能会有意想不到的特别之处。

但是有点很好奇。bind了之后的函数假如写在事件里时,要传参的话,也是需要将它构造成一个匿名函数来使用。

所以有没有办法可以尽量避免呢?

渲染的时候都会过一遍绑定的事件的吗?