我有一个Parent组件App和一个嵌套组件SearchByForm。 SearchByForm包含一个单选按钮的组,我正在尝试修改第三个按钮的值以使其处于选中状态(true)。可以通过其className .workstationRadioBtn进行标识。
SearchByForm类
import React from 'react';
class SearchByForm extends React.Component {
constructor(props) {
super(props);
this.state = { which: 'order' };
}
buttonChange = (e) => {
if (e.target.checked) {
this.setState({ which: e.target.value });
this.props.updateFromSearchByForm(e.target.value);
}
}
render() {
return (
<form className="SearchByForm">
<div className="form-check">
<label>
<input
type="radio"
name="searchBy"
value="order"
checked={this.state.which === 'order'}
onChange={this.buttonChange}
className="orderRadioBtn"
/>
Order
</label>
</div>
<div className="form-check">
<label>
<input
type="radio"
name="searchBy"
value="employee"
checked={this.state.which === 'employee'}
onChange={this.buttonChange}
className="employeeRadioBtn"
/>
Employee
</label>
</div>
<div className="form-check">
<label>
<input
type="radio"
name="searchBy"
value="workstation"
checked={this.state.which === 'workstation'}
onChange={this.buttonChange}
className="workstationRadioBtn"
/>
Work Station
</label>
</div>
</form>
);
}
}
export default SearchByForm;
搜索组件类:
class Search extends React.Component {
constructor(props) {
super(props);
this.state = { searchKey: '_id', searchBy: 'order', searchResults: null };
this.updateFromSearchByForm = this.updateFromSearchByForm.bind(this);
this.updateFromKeysForm = this.updateFromKeysForm.bind(this);
this.clearSearchResults = this.clearSearchResults.bind(this);
this.populateSearchResults = this.populateSearchResults.bind(this);
}
updateFromSearchByForm(value) {
this.setState({ searchBy: value });
}
updateFromKeysForm(value) {
this.setState({ searchKey: value });
}
keyToSearchBy = () => {
switch (this.state.searchBy) {
case 'order':
return (
<KeysForm which='order' updateFromKeysForm={this.updateFromKeysForm}></KeysForm>
);
case 'employee':
return (
<KeysForm which='employee' updateFromKeysForm={this.updateFromKeysForm}></KeysForm>
);
case 'workstation':
return (
<KeysForm which='workstation' updateFromKeysForm={this.updateFromKeysForm}></KeysForm>
);
default:
return (
<KeysForm which='order' updateFromKeysForm={this.updateFromKeysForm}></KeysForm>
);
}
}
clearSearchResults = () => {
this.setState({ searchResults: null });
}
populateSearchResults = (results) => {
this.setState({ searchResults: results });
}
displayOrderResults = () => {
let list = [];
let count = 0;
list.push(<label> Orders found that match your search criteria:</label>)
for (let result of this.state.searchResults) {
list.push(
<ListGroupItem key={count}>ID: {result._id}, OrderID: {result.OrderID}, CustomerID: {result.CustomerID}, DateRequired: {result.DateRequired}, Status: {result.Status}, PriorityFlag: {result.PriorityFlag}</ListGroupItem>
)
count++;
}
return list;
}
displayEmployeeResults = () => {
let list = [];
let count = 0;
list.push(<label> Employees found that match your search criteria:</label>)
for (let result of this.state.searchResults) {
list.push(
<ListGroupItem key={count}>ID: {result._id}, Staff Name: {result.WorkerName}</ListGroupItem>
)
count++;
}
return list;
}
displayWorkStationResults = () => {
let list = [];
let count = 0;
list.push(<label> Stations found that match your search criteria:</label>)
for (let result of this.state.searchResults) {
list.push(
<ListGroupItem key={count}>ID: {result._id}, Work Station Name: {result.StationName}</ListGroupItem>
)
count++;
}
return list;
}
showSearchResults = () => {
//Know how to display based on searchBy type.
switch (this.state.searchBy) {
case 'order':
return (this.displayOrderResults());
case 'employee':
return (this.displayEmployeeResults());
case 'workstation':
return (this.displayWorkStationResults());
default:
break;
}
for (let result of this.state.searchResults) {
console.log(result);
}
}
render() {
return (
<Jumbotron>
<div className="App">
<div className='header'>
<div className='header-space1'>
<div className='button-header'>
<Link to='/menu'>
<Button id='menu'>Back to Menu</Button>
</Link>
</div>
</div>
<div className='header-space2'>
<h2>Search</h2>
</div>
<div className='header-space3'>
<div className='button-header'>
</div>
</div>
</div>
<div className='Search'>
<div className='Row'>
<div className='SearchForm'>
<p>What would you like to search by?</p>
<SearchByForm updateFromSearchByForm={this.updateFromSearchByForm}></SearchByForm>
{this.keyToSearchBy()}
</div>
</div>
<ValueForm searchKey={this.state.searchKey} searchBy={this.state.searchBy} clearSearchResults={this.clearSearchResults} populateSearchResults={this.populateSearchResults}></ValueForm>
<br></br>
<div className='Row'>
<div className='SearchResults'>
<p>Search Results</p>
{this.state.searchResults ?
<ListGroup>
{this.showSearchResults()}
</ListGroup>
:
null}
</div>
</div>
</div>
</div>
</Jumbotron>
);
}
}
该测试当前会创建完整的树副本,并成功将.workstationRadioBtn的检查值检查为true。它还成功地将SearchByForm的“哪个”状态字段更改为“工作站”。 我测试的当前状态如下
describe('Work Station Search', () => {
it(' successfully selects order radio button', () => {
const wrapper = mount(
<Router>
<Search />
</Router>
);
console.log(wrapper.debug());
const wrapperSearchByForm = wrapper.find(SearchByForm);
wrapperSearchByForm.find('input').filter('.workstationRadioBtn').simulate('change', {target: {checked: true}});
wrapperSearchByForm.setState({ which: 'workstation' });
wrapper.update();
console.log(wrapper.debug());
})
});
该测试的调试代码表明上述内容是正确的,但是update()似乎没有成功地重新渲染第二个嵌套组件KeysForm,其返回的渲染依赖于SearchByForm。仍然好像选中了“订购”单选按钮一样。
这是测试的完整调试输出:
console.log src/__tests__/Search/Search.test.js:84
<BrowserRouter>
<Router history={{...}}>
<Search>
<Jumbotron fluid={false}>
<div className="jumbotron">
<div className="App">
<div className="header">
<div className="header-space1">
<div className="button-header">
<Link to="/menu">
<LinkAnchor href="/menu" navigate={[Function: navigate]}>
<a href="/menu" onClick={[Function: onClick]}>
<Button id="menu" variant="primary" active={false} disabled={false} type="button">
<button id="menu" disabled={false} type="button" className="btn btn-primary">
Back to Menu
</button>
</Button>
</a>
</LinkAnchor>
</Link>
</div>
</div>
<div className="header-space2">
<h2>
Search
</h2>
</div>
<div className="header-space3">
<div className="button-header" />
</div>
</div>
<div className="Search">
<div className="Row">
<div className="SearchForm">
<p>
What would you like to search by?
</p>
<SearchByForm updateFromSearchByForm={[Function: bound updateFromSearchByForm]}>
<form className="SearchByForm">
<div className="form-check">
<label>
<input type="radio" name="searchBy" value="order" checked={true} onChange={[Function]} className="orderRadioBtn" />
Order
</label>
</div>
<div className="form-check">
<label>
<input type="radio" name="searchBy" value="employee" checked={false} onChange={[Function]} className="employeeRadioBtn" />
Employee
</label>
</div>
<div className="form-check">
<label>
<input type="radio" name="searchBy" value="workstation" checked={false} onChange={[Function]} className="workstationRadioBtn" />
Work Station
</label>
</div>
</form>
</SearchByForm>
<KeysForm which="order" updateFromKeysForm={[Function: bound updateFromKeysForm]}>
<div className="KeysForm">
<div className="OrderKeys">
<p>
Which Order Key would you like to search by?
</p>
<form>
<div className="form-check">
<label>
<input type="radio" name="orderKey" value="_id" checked={true} onChange={[Function]} className="form-check-input" />
Id
</label>
</div>
<div className="form-check">
<label>
<input type="radio" name="orderKey" value="DateRequired" checked={false} onChange={[Function]} className="form-check-input" />
Date Required
</label>
</div>
<div className="form-check">
<label>
<input type="radio" name="orderKey" value="Status" checked={false} onChange={[Function]} className="form-check-input" />
Status
</label>
</div>
<div className="form-check">
<label>
<input type="radio" name="orderKey" value="PriorityFlag" checked={false} onChange={[Function]} className="form-check-input" />
Priority Flag
</label>
</div>
</form>
</div>
</div>
</KeysForm>
</div>
</div>
<ValueForm searchKey="_id" searchBy="order" clearSearchResults={[Function: bound ]} populateSearchResults={[Function: bound ]}>
<form className="ValueForm">
<label>
<input type="text" name="value" value="" onChange={[Function]} />
</label>
<Button onClick={[Function]} variant="primary" active={false} disabled={false} type="button">
<button onClick={[Function]} disabled={false} type="button" className="btn btn-primary">
Search
</button>
</Button>
</form>
</ValueForm>
<br />
<div className="Row">
<div className="SearchResults">
<p>
Search Results
</p>
</div>
</div>
</div>
</div>
</div>
</Jumbotron>
</Search>
</Router>
</BrowserRouter>