使用Dan Abramov has previously discussed 的表示和容器组件,我有一个表示组件,它有一个输入和按钮以及一个容器组件,它处理从输入给出的文本,并在按下选择按钮时调度一个事件。
演示组件:
import React from 'react'
const NavBar = ({ onClick, handleChange }) => {
return (
<div className="NavBar">
<input onChange={handleChange} />
<button type="submit" onClick={onClick}>Search</button>
</div>
)
}
export default NavBar
容器组件:
import {connect} from 'react-redux'
import NavBar from '../components/NavBar'
import {requestStat} from '../../stats/actions/StatsAction'
// meh, not a big fan of this, but I think it's the right compromise for handling the textinput.
let textInput
const mapDispatchToProps = (dispatch) => ({
handleChange: (e) => textInput = e.target.value,
onClick : (e) => handleSelectedTab(dispatch)
})
const handleSelectedTab = (dispatch) => {
if (textInput != null && textInput != "") {
dispatch(requestStat(textInput))
}
}
const NavBarContainer = connect(null, mapDispatchToProps)(NavBar)
我想知道存储输入字符串的最佳位置是什么?
在我目前的解决方案中,我将此状态存储在容器组件的textInput变量中 - 这是当前设置的最佳位置吗?
我以前将此值存储为演示组件中的变量,然后在按下提交时将值传递给容器,但这并不是很正确。将输入值存储在容器中的优点是,表示组件不会假设如何处理输入文本,除了运行handleChange回调并将此回调注入到表示组件中对此行为的自然单元测试:
export default NavBarContainer
import React from 'react'
import {shallow} from 'enzyme'
import Navbar from './Navbar'
describe('NavBar', () =>{
it ('run callback when input changed, setting value to true', () => {
let change = false
const handleChange = () => { change = true; }
const props = { handleChange }
const component = shallow(<Navbar {...props} />)
expect(change).toBe(false)
const formGroup = component.find('input')
formGroup.simulate('change')
expect(change).toBe(true)
})
})
非常感谢任何想法/最佳做法或建议!
修改
澄清;我已经有一个redux存储和操作,但每次有人在输入字段中键入一个字符时,更新存储似乎有点过分。
一旦用户点击提交,我也不需要存储此值,因为事件由传奇获取,然后传统使用它来从Web服务器获取数据,其结果是通过减速机进入redux商店。
编辑2:
我也不愿意使用组件状态,因为更新它会导致重新呈现,并且由于其异步性质,我不能轻易相信它在用户点击时已经更新按钮。
答案 0 :(得分:1)
实际上,大多数情况都取决于您的用例,例如您希望组件的确切要求。
例如,如果您的组件只有输入和一个按钮,那么最好将其输入保存在容器中。想象一下,如果您将文本输入处理程序保留在此组件本身并且仅通过按钮单击处理程序,那么它现在可能会起作用,但将来如果您想在用户单击按钮之前处理输入文本该怎么办。例如,您可能希望稍后在此输入框中限制输入字符,然后您可能必须在组件中进行一些修改。
还有一个例子可能就像假设您想要制作组件,当按下按钮时会对输入值进行一些处理,就像电子邮件验证一样。那时将输入值保留在组件本身中是有意义的。因此,每按一次按钮,然后验证电子邮件ID,然后只调用作为prop传递给它的按钮处理程序。这将成为您的应用程序的电子邮件验证程序组件。
虽然这只是一个粗略的例子,但它足以澄清我的观点。实际上,组件应该足够灵活,以便尽可能多地使用它们。
答案 1 :(得分:0)
您正在使用redux并已连接您的组件。您应该将其存储在您的redux store
中,并在mapStateToProps
方法中添加connect()
。
mapStateToProps = ( state ) = > {
return {
inutText: state.inputText
}
}
const NavBarContainer = connect(mapStateToProps, mapDispatchToProps)(NavBar);
然后只为你的NavBar制作一个减速器和一个处理变化的动作。
编辑:解决您的评论;
每当有人输入某个角色时,您都必须更新某些内容。它是一个非常轻量级的模块,更新速度非常快。即使你你正在返回整个州,你实际上只是更新了那个属性。考虑到你没有在redux中改变状态,所有其他属性只指向内存中的相同位置。你只是指定一个指针。
编辑#2:
商店中的值始终可用。您可以随时获取并操纵值以执行任何操作。如果卸载组件后不需要输入值,那么我会将其保持在容器状态。否则我会把它放在商店里。
请记住,如果用户导航离开,您可以使用商店中的值来导航hydrateState,如果它在商店中,则可以重新填充它们的值。
如果你想处理组件内部的状态,我会这样做。
import React, { PureComponent } from "react";
import {connect} from 'react-redux';
import NavBar from '../components/NavBar';
import {requestStat} from '../../stats/actions/StatsAction';
class navBar extends PureComponent {
constructor( props ) {
super( props );
this.state = {
textInput: props.textInput || ""
}
this.handleSelectedTab = this.handleSelectedTab.bind( this );
this.handleChange = this.handleChange.bind( this );
}
handleSelectedTab() {
// I don't see where you use this
// dispatch is available here.
// this.props.dispatch
}
handleChange( e ) {
// handle change
}
render() {
const { textInput } = this.state;
return (
<NavBar onClick={ this.handleSelectedTab } handleChange={ this.handleChange } value={ textInput } />
);
}
}
const NavBarContainer = connect()(navBar);
export default NavBarContainer;
你拥有它的方式不允许有多个组件。他们会踩到对方。
答案 2 :(得分:0)
对于React应用程序,您可以将其保存在组件的状态中,但对于React with Redux,最好的办法是将状态保存在Redux提供的存储中。
要完成此操作,您需要设置一些动作创建器和减速器。请查看TodoList example app,了解我所谈论的内容。通常,您将使用操作文件来编写通过容器组件作为道具传递给演示组件的简单函数。
基于评论更新:
您可以使用类似
的内容import React, { PropTypes } from 'react'
class NavBar extends React.Component {
static propTypes = { onClick: PropTypes.func.isRequired }
handleChange = (e) => this.setState({inputValue: e.target.value})
onClick = (e) => this.props.onClick(this.state.inputValue)
render(){
return (
<div className="NavBar">
<input onChange={handleChange} />
<button type="submit" onClick={onClick}>Search</button>
</div>
)
}
}
export default NavBar