修改:我没有提供所有代码来保持这篇文章的篇幅不长,但是请告诉我我需要提供的其他信息/代码片段给出背景信息。
我是一名React / Redux初学者尝试使用Redux存储某些状态变量,因为用户从 SearchForm 组件导航到 ResultsTable 组件 - 这两者都是组件包装在 ParentContainer 组件中。我发现每次更新ParentContainer重新渲染子组件时都会重置我的Redux存储。
ParentContainer 的渲染功能看起来像这样:
if (this.state.currentPage === "search"){
content = <ResultsTable searchResults={this.props.searchResults}/>
} else if (this.state.currentPage === "search_form"){
content = <SearchForm/>}
return(
<div>
<Header/>
{content}
<FooterPanel/>
</div>
);
基本上,我正在使用一些条件逻辑来选择在 Header 和 Footer 组件之间呈现哪个组件。我的搜索表单有一个文本输入和单选按钮,用于确定要执行的搜索类型:
<form id="search-form" className="form" action="/auth/search" method="post">
<input type="text" id="search" className="text-input" name="search" placeholder="search stuff here"/>
<div className="radio">
<label>
<input type="radio" name="searchType" value="first"
checked={this.state.selectedOption === 'first'}
onChange={this.handleOptionChange} />
First Search Type
</label>
</div>
<div className="radio">
<label>
<input type="radio" name="searchType" value="second"
checked={this.state.selectedOption === 'second'}
onChange={this.handleOptionChange} />
Second Type of Search
</label>
</div>
<div>
<button type="submit" onClick={this.handleSearchClick} className="button">Search</button>
</div>
</form>
我还将 SearchForm , ParentContainer 和标题与我的Redux商店相关联:
const mapStateToProps = (state)=> {
return {
searchResults: state.searchResults,
searchType: state.searchType
}
}
export default connect(mapStateToProps)(SearchForm);
我的 configureStore.js :
export default () => {
const store = createStore(
combineReducers({
searchResults: SearchResultReducer,
searchType: searchTypeReducer,
})
);
return store;
}
我遇到的问题是当我从 SearchForm 转换为 ResultsTable 时我的 searchType 状态变量不会保留/ em>的。我需要该变量来确定要呈现的输出类型(图表,表格等)。
当我在 SearchForm 上点击我的不同单选按钮时,我发现我的商店状态确实正在更新(使用Chrome开发者工具控制台):
searchResults:[]
searchType: {searchType: "first", searchText: "DefaultText"}
我正在为 onClick 按钮事件使用 handleSearchClick()处理程序:
handleSearchClick(event){
console.log("Search Button clicked")
this.setState(()=>{
return{
loading: true,
selectedOption: this.state.selectedOption
}
})
this.props.dispatch(setSearchType(this.state.selectedOption));
}
但是,一旦我点击搜索按钮,从后端获取结果,然后渲染 ResultsTable ,我的状态将再次重置为DefaultType
:
searchResults:[...results]
searchType: {searchType: "DefaultType", searchText: "DefaultText"}
我几乎可以肯定它在我的开发者控制台中与这两个输出有关:
Inside search result reducer
search-results.js?337d:9 {type: "@@redux/INIT"}type: "@@redux/INIT"__proto__: Object
search-results.js?337d:25 DEFAULT CALLED
search-results.js?337d:8 Inside search result reducer
search-results.js?337d:9 {type: "@@redux/PROBE_UNKNOWN_ACTION_5.z.q.e.6.d"}type: "@@redux/PROBE_UNKNOWN_ACTION_5.z.q.e.6.d"__proto__: Object
search-results.js?337d:25 DEFAULT CALLED
search-type.js?0d78:8 Inside search type reducer...
search-type.js?0d78:9 {type: "@@redux/INIT"}
search-type.js?0d78:8 Inside search type reducer...
search-type.js?0d78:9 {type: "@@redux/PROBE_UNKNOWN_ACTION_s.n.0.x.n.k"}
每当我更新 ParentContainer 时,看起来Redux正在重新创建我的商店。这个StackOverflow post says that Redux store will reset when a page is reloaded,但我没有重新加载页面 - 我只是在 ParentContainer 中重新渲染子组件。此外,我的 searchTypeReducer 应返回默认状态对象,该对象应包含来自 SearchForm 的所选单选按钮值:
const searchTypeReducer = (state = searchTypeDefaultState, action) => {
console.log("Inside search type reducer...")
console.log(action)
switch(action.type){
case 'SET_SEARCH_TYPE':
console.log("SEARCH TYPE SETTING")
return {
...state,
searchType: action.searchType
};
case 'SET_SEARCH_TEXT':
console.log("SEARCH TEXT SETTING");
return {
...state,
searchText: action.searchType
}
default: // Redux upon initialization of the store should go here! But my state is already defined!
console.log("Search type default called!")
return state;
}
}
我正在 app.js 文件中呈现我的提供商:
const jsx = (
<Provider store={store}>
<AppRouter/>
</Provider>
)
ReactDOM.render(jsx, document.getElementById('parentContainer'));
我的componentDidMount
有componentDidUpdate
和ParentContainer
,但请注意,很多代码都在调试console.log()
语句,因为我试图弄清楚是什么继续:
componentDidUpdate(prevProps,prevState){
console.log("COMPONENT UPDATED");
console.log("THIS IS MY CURRENT STATE")
console.log(store.getState());
}
componentDidMount(){
console.log("Parent Container was loaded.");
// I added this sessionStorage item in later as a workaround for now
var searchType = sessionStorage.getItem("searchType")
console.log("Parent container props: ", this.props);
let jsonResults = this.processSearchResults(searchResults);
console.log("Current searchResults: ", jsonResults)
var arrayResults = this.createSearchResultArray(jsonResults)
console.log("Inside parent container, checking props!")
console.log(this.props)
for (var result in arrayResults){
switch(searchType){
case "first":
this.props.dispatch(addFirst({...arrayResults[result]}));
case "second":
this.props.dispatch(addSecond({...arrayResults[result]}))
}
}
console.log(this.props);
}
当我重新渲染ParentContainer时,有没有办法阻止Redux重置我的商店?
或者这是使用本地存储的最佳技术吗?
第二次修改:
我还可以通过简单地将选中的单选按钮选项存储在本地存储中来轻松解决此问题:
handleSearchClick(event){
console.log("Search Button clicked")
localStorage.setItem("searchType", this.state.selectedOption);
}
然后从我的 ResultsTable 组件类调用localStorage.getItem("searchType")
。
但我仍然很想知道在概念上是否有办法在Redux中执行此操作。