1. SearhBox作成
components/layout/SearchBox.js
import React, { useState } from 'react';
import { Form, Button } from 'react-bootstrap';
const SearchBox = ({ history }) => {
const [keyword, setKeyword] = useState('');
const submitHandler = (e) => {
e.preventDefault();
if (keyword.trim()) {
history.push(`/search/${keyword}`);
} else {
history.push('/');
}
};
return (
<Form onSubmit={submitHandler} inline>
<Form.Control
type="text"
name="q"
onChange={(e) => setKeyword(e.target.value)}
placeholder="Search Products..."
className="mr-sm-2 ml-sm-5"
></Form.Control>
<Button type="submit" variant="outline-success" className="p-2">
Search
</Button>
</Form>
);
};
export default SearchBox;
2. search/:keywordのRoute設置
components/routing/Routes.js
//...
const Routes = () => {
//...
<Route exact path="/profile/:id" component={Profile} />
+ <Route exact path="/search/:keyword" component={Posts} />
<Route exact path="/posts" component={Posts} />
<Route exact path="/posts/:id" component={Post} />
//...
3. Navbarに検索フォーム設置
components/layout/Navbar.js
//...
import PropTypes from 'prop-types';
+ import SearchBox from './SearchBox';
import { logout } from '../../actions/auth';
const Navbar = ({ auth: { isAuthenticated, loading }, logout }) => {
//...
return (
<nav className="navbar bg-dark">
<h1>
<Link to="/posts">
<i className="fas fa-code" /> Refnote
</Link>
</h1>
+ <Route render={({ history }) => <SearchBox history={history} />} />
{!loading && (
<Fragment>{isAuthenticated ? authLinks : guestLinks}</Fragment>
)}
</nav>
);
};
//...
4. Posts一覧にkeyword Params設置
components/posts/Posts.js
//...
import { getPosts } from '../../actions/post';
+ const Posts = ({ getPosts, post: { posts, loading }, match, auth }) => {
+ const keyword = match.params.keyword;
useEffect(() => {
+ getPosts(keyword);
+ }, [getPosts, keyword]);
return loading ? (
//...
<div className="Posts">
{posts.map((post) => (
<PostItem key={post._id} post={post} />
))}
</div>
</Fragment>
);
};
//...
5. getPostsアクションにKeyword Propsを設置
actions/post.js
//...
// Get posts
+ export const getPosts = (keyword = '') => async (dispatch) => {
try {
+ const res = await axios.get(`/api/posts?keyword=${keyword}`);
dispatch({
type: GET_POSTS,
payload: res.data,
});
} catch (err) {
dispatch({
type: POST_ERROR,
payload: { msg: err.response.statusText, status: err.response.status },
});
}
};
//...
6. postsAPIを編集
routes/api/posts.js
//...
// @route GET api/posts
// @desc Get all posts
// @access Public
router.get('/', async (req, res) => {
+ const keyword = req.query.keyword
+ ? {
+ text: {
+ $regex: req.query.keyword,
+ $options: 'i',
+ },
+ }
+ : {};
try {
+ const posts = await Post.find({ ...keyword }).sort({ date: -1 });
res.json(posts);
} catch (err) {
console.error(err.message);
res.status(500).send('Server Error');
}
});
//...