如何解决 React.js 中的路由问题?
How Can I Fix This Routing Issue In React.js?
我会先声明这是我在 Node 或 React.js 上工作的第四天,所以请多多包涵。
我正在为 Docusaurus 2 构建一个自定义的离线搜索功能。我已经构建了一个 JSON 索引并创建了一个使用 elasticlunr 进行搜索的函数。我想重定向到一个单独的结果页面,但是尽管尝试遵循多个示例,但我在重定向方面遇到了问题。这是我的 index.js
SearchBar。
import React, {Component} from 'react';
import {Redirect} from 'react-router-dom';
import classnames from 'classnames';
import elasticlunr from 'elasticlunr';
let siteIndex = require('./siteIndex.json');
class Search extends Component {
constructor(props) {
super(props);
this.state = {
results: [],
term: '',
index: elasticlunr(function () {
this.setRef('id');
this.addField('title');
this.addField('body');
this.addField('url');
})
};
this.toggleSearchPressEnter = this.toggleSearchPressEnter.bind(this);
this.changeTerm = this.changeTerm.bind(this);
}
init() {
let siteIndexKeys = Object.keys(siteIndex);
siteIndexKeys.forEach(key => {
this.state.index.addDoc(siteIndex[key]);
});
}
changeTerm(e) {
this.setState({term: e.target.value});
}
toggleSearchPressEnter(e) {
if (e.key === "Enter") {
this.init();
let siteSearch = this.state.index.search(e.target.value, {}); // Empty dictionary here fixes the warning about using the default configuration because you didn't supply one!
let docs = this.state.index.documentStore.docs;
this.state.results = siteSearch.slice(0, 5).map(searchKey => docs[searchKey.ref]);
if (this.state.results.length > 0) {
this.renderRedirect();
}
}
}
renderRedirect() {
console.log("Go home!");
console.log(this.state.results.length);
console.log(this.state.results);
// window.location = "/"
<Redirect
to={{
pathname: '/',
state: { results: this.state.results }
}}
/>
}
render() {
return (
<div className="navbar__search" key="search-box">
<span
aria-label="expand searchbar"
role="button"
className={classnames('search-icon', {
'search-icon-hidden': this.props.isSearchBarExpanded,
})}
tabIndex={0}
/>
<input
id="search_input_react"
type="search"
placeholder="Search"
aria-label="Search"
className={classnames(
'navbar__search-input',
{'search-bar-expanded': this.props.isSearchBarExpanded},
{'search-bar': !this.props.isSearchBarExpanded},
)}
onKeyPress={this.toggleSearchPressEnter}
/>
</div>
);
}
}
export default Search;
因为我们在重定向到结果页面时遇到问题,我想看看我是否可以直接转到主页。当用户在搜索栏上按回车键时,我在浏览器控制台中看到消息 "Go home!",但没有发生重定向。如果我从 renderRedirect()
.
中注释掉 Redirect
,我已经注释掉了确实有效的 javascript 重定向
我尝试在 Redirect
周围添加一个 return()
,但似乎没有任何区别。
如果您想重现问题
npx @docusaurus/init@next init docs classic
npm run swizzle @docusaurus/theme-search-algolia SearchBar
将src/theme/SearchBar/index.js
的内容替换为上述问题的代码。
要生成 JSON 索引:
生成-index.js
const fs = require('fs-extra');
const path = require('path');
const removeMd = require('remove-markdown');
let searchId = 0;
const searchDoc = {};
async function readAllFilesAndFolders(folder) {
try {
const topFilesAndFolders = fs.readdirSync(folder);
for (let i = 0; i < topFilesAndFolders.length; i++) {
const file = topFilesAndFolders[i];
const fileOrFolderPath = `${folder}/${file}`;
const stat = fs.lstatSync(fileOrFolderPath);
if (stat.isFile() && path.extname(fileOrFolderPath) === '.md') {
console.log(`Got Markdown File ${file}`);
fs.readFile(fileOrFolderPath, (err, data) => {
if (err) throw err;
const regex = /title: .*\n/g;
let search = data.toString().match(regex);
let docTitle = search[0].toString().replace("title: ", "");
console.log("doctitle: ", docTitle);
if (!docTitle) {
docTitle = file.replace('.md', '');
generateSearchIndexes(fileOrFolderPath, file, docTitle);
}
else {
generateSearchIndexes(fileOrFolderPath, file, docTitle);
}
});
} else if (stat.isDirectory()) {
console.log(`Got Directory ${file}, Started Looking into it`);
readAllFilesAndFolders(fileOrFolderPath, file);
}
}
} catch (error) {
console.log(error);
}
}
function generateSearchIndexes(fileOrFolderPath, file, docTitle) {
try {
let fileContent = fs.readFileSync(fileOrFolderPath, 'utf-8');
let body = removeMd(fileContent).replace(/^\s*$(?:\r\n?|\n)/gm, '');
let title = docTitle.trim();
let url = fileOrFolderPath
.replace('.md', '')
.trim();
searchDoc[file.replace('.md', '').toLowerCase()] = { id: searchId, title, body, url };
fs.writeFileSync('src/theme/SearchBar/siteIndex.json', JSON.stringify(searchDoc), 'utf-8');
searchId = searchId + 1;
} catch (error) {
console.log('Failed to generate fail:', error);
}
}
readAllFilesAndFolders('docs');
从默认文档构建 JSON 索引后,即可尝试搜索。我没有做任何其他更改。
我可能做了一些愚蠢的事情,希望它很容易修复,所以请宽恕。我真的试过了。 ;)
根据 Ajay 的一些指导,并稍微尝试一下,我有了一个可行的解决方案。
import React, {Component} from 'react';
import {Redirect} from 'react-router';
import classnames from 'classnames';
import elasticlunr from 'elasticlunr';
let siteIndex = require('./siteIndex.json');
class Search extends Component {
constructor(props) {
super(props);
this.state = {
results: [],
term: '',
search: '',
index: elasticlunr(function () {
this.setRef('id');
this.addField('title');
this.addField('body');
this.addField('url');
})
};
this.toggleSearchPressEnter = this.toggleSearchPressEnter.bind(this);
this.changeTerm = this.changeTerm.bind(this);
}
init() {
let siteIndexKeys = Object.keys(siteIndex);
siteIndexKeys.forEach(key => {
this.state.index.addDoc(siteIndex[key]);
});
}
changeTerm(e) {
this.setState({term: e.target.value});
}
toggleSearchPressEnter(e) {
if (e.key === "Enter") {
this.init();
let searchTerm = e.target.value;
let siteSearch = this.state.index.search(searchTerm, {}); // Empty dictionary here fixes the warning about using the default configuration because you didn't supply one!
let docs = this.state.index.documentStore.docs;
let searchResults = siteSearch.slice(0, 5).map(searchKey => docs[searchKey.ref]);
this.setState({
results: searchResults,
search: searchTerm,
});
}
}
render() {
if (this.state.results.length >= 1) {
return <Redirect to={{
pathname: '/results',
state: {
results: this.state.results,
search: this.state.search
}
}} />
}
return (
<div className="navbar__search" key="search-box">
<span
aria-label="expand searchbar"
role="button"
className={classnames('search-icon', {
'search-icon-hidden': this.props.isSearchBarExpanded,
})}
tabIndex={0}
/>
<input
id="search_input_react"
type="search"
placeholder="Search"
aria-label="Search"
className={classnames(
'navbar__search-input',
{'search-bar-expanded': this.props.isSearchBarExpanded},
{'search-bar': !this.props.isSearchBarExpanded},
)}
onKeyPress={this.toggleSearchPressEnter}
/>
</div>
);
}
}
export default Search;
我会先声明这是我在 Node 或 React.js 上工作的第四天,所以请多多包涵。
我正在为 Docusaurus 2 构建一个自定义的离线搜索功能。我已经构建了一个 JSON 索引并创建了一个使用 elasticlunr 进行搜索的函数。我想重定向到一个单独的结果页面,但是尽管尝试遵循多个示例,但我在重定向方面遇到了问题。这是我的 index.js
SearchBar。
import React, {Component} from 'react';
import {Redirect} from 'react-router-dom';
import classnames from 'classnames';
import elasticlunr from 'elasticlunr';
let siteIndex = require('./siteIndex.json');
class Search extends Component {
constructor(props) {
super(props);
this.state = {
results: [],
term: '',
index: elasticlunr(function () {
this.setRef('id');
this.addField('title');
this.addField('body');
this.addField('url');
})
};
this.toggleSearchPressEnter = this.toggleSearchPressEnter.bind(this);
this.changeTerm = this.changeTerm.bind(this);
}
init() {
let siteIndexKeys = Object.keys(siteIndex);
siteIndexKeys.forEach(key => {
this.state.index.addDoc(siteIndex[key]);
});
}
changeTerm(e) {
this.setState({term: e.target.value});
}
toggleSearchPressEnter(e) {
if (e.key === "Enter") {
this.init();
let siteSearch = this.state.index.search(e.target.value, {}); // Empty dictionary here fixes the warning about using the default configuration because you didn't supply one!
let docs = this.state.index.documentStore.docs;
this.state.results = siteSearch.slice(0, 5).map(searchKey => docs[searchKey.ref]);
if (this.state.results.length > 0) {
this.renderRedirect();
}
}
}
renderRedirect() {
console.log("Go home!");
console.log(this.state.results.length);
console.log(this.state.results);
// window.location = "/"
<Redirect
to={{
pathname: '/',
state: { results: this.state.results }
}}
/>
}
render() {
return (
<div className="navbar__search" key="search-box">
<span
aria-label="expand searchbar"
role="button"
className={classnames('search-icon', {
'search-icon-hidden': this.props.isSearchBarExpanded,
})}
tabIndex={0}
/>
<input
id="search_input_react"
type="search"
placeholder="Search"
aria-label="Search"
className={classnames(
'navbar__search-input',
{'search-bar-expanded': this.props.isSearchBarExpanded},
{'search-bar': !this.props.isSearchBarExpanded},
)}
onKeyPress={this.toggleSearchPressEnter}
/>
</div>
);
}
}
export default Search;
因为我们在重定向到结果页面时遇到问题,我想看看我是否可以直接转到主页。当用户在搜索栏上按回车键时,我在浏览器控制台中看到消息 "Go home!",但没有发生重定向。如果我从 renderRedirect()
.
Redirect
,我已经注释掉了确实有效的 javascript 重定向
我尝试在 Redirect
周围添加一个 return()
,但似乎没有任何区别。
如果您想重现问题
npx @docusaurus/init@next init docs classic
npm run swizzle @docusaurus/theme-search-algolia SearchBar
将src/theme/SearchBar/index.js
的内容替换为上述问题的代码。
要生成 JSON 索引:
生成-index.js
const fs = require('fs-extra');
const path = require('path');
const removeMd = require('remove-markdown');
let searchId = 0;
const searchDoc = {};
async function readAllFilesAndFolders(folder) {
try {
const topFilesAndFolders = fs.readdirSync(folder);
for (let i = 0; i < topFilesAndFolders.length; i++) {
const file = topFilesAndFolders[i];
const fileOrFolderPath = `${folder}/${file}`;
const stat = fs.lstatSync(fileOrFolderPath);
if (stat.isFile() && path.extname(fileOrFolderPath) === '.md') {
console.log(`Got Markdown File ${file}`);
fs.readFile(fileOrFolderPath, (err, data) => {
if (err) throw err;
const regex = /title: .*\n/g;
let search = data.toString().match(regex);
let docTitle = search[0].toString().replace("title: ", "");
console.log("doctitle: ", docTitle);
if (!docTitle) {
docTitle = file.replace('.md', '');
generateSearchIndexes(fileOrFolderPath, file, docTitle);
}
else {
generateSearchIndexes(fileOrFolderPath, file, docTitle);
}
});
} else if (stat.isDirectory()) {
console.log(`Got Directory ${file}, Started Looking into it`);
readAllFilesAndFolders(fileOrFolderPath, file);
}
}
} catch (error) {
console.log(error);
}
}
function generateSearchIndexes(fileOrFolderPath, file, docTitle) {
try {
let fileContent = fs.readFileSync(fileOrFolderPath, 'utf-8');
let body = removeMd(fileContent).replace(/^\s*$(?:\r\n?|\n)/gm, '');
let title = docTitle.trim();
let url = fileOrFolderPath
.replace('.md', '')
.trim();
searchDoc[file.replace('.md', '').toLowerCase()] = { id: searchId, title, body, url };
fs.writeFileSync('src/theme/SearchBar/siteIndex.json', JSON.stringify(searchDoc), 'utf-8');
searchId = searchId + 1;
} catch (error) {
console.log('Failed to generate fail:', error);
}
}
readAllFilesAndFolders('docs');
从默认文档构建 JSON 索引后,即可尝试搜索。我没有做任何其他更改。
我可能做了一些愚蠢的事情,希望它很容易修复,所以请宽恕。我真的试过了。 ;)
根据 Ajay 的一些指导,并稍微尝试一下,我有了一个可行的解决方案。
import React, {Component} from 'react';
import {Redirect} from 'react-router';
import classnames from 'classnames';
import elasticlunr from 'elasticlunr';
let siteIndex = require('./siteIndex.json');
class Search extends Component {
constructor(props) {
super(props);
this.state = {
results: [],
term: '',
search: '',
index: elasticlunr(function () {
this.setRef('id');
this.addField('title');
this.addField('body');
this.addField('url');
})
};
this.toggleSearchPressEnter = this.toggleSearchPressEnter.bind(this);
this.changeTerm = this.changeTerm.bind(this);
}
init() {
let siteIndexKeys = Object.keys(siteIndex);
siteIndexKeys.forEach(key => {
this.state.index.addDoc(siteIndex[key]);
});
}
changeTerm(e) {
this.setState({term: e.target.value});
}
toggleSearchPressEnter(e) {
if (e.key === "Enter") {
this.init();
let searchTerm = e.target.value;
let siteSearch = this.state.index.search(searchTerm, {}); // Empty dictionary here fixes the warning about using the default configuration because you didn't supply one!
let docs = this.state.index.documentStore.docs;
let searchResults = siteSearch.slice(0, 5).map(searchKey => docs[searchKey.ref]);
this.setState({
results: searchResults,
search: searchTerm,
});
}
}
render() {
if (this.state.results.length >= 1) {
return <Redirect to={{
pathname: '/results',
state: {
results: this.state.results,
search: this.state.search
}
}} />
}
return (
<div className="navbar__search" key="search-box">
<span
aria-label="expand searchbar"
role="button"
className={classnames('search-icon', {
'search-icon-hidden': this.props.isSearchBarExpanded,
})}
tabIndex={0}
/>
<input
id="search_input_react"
type="search"
placeholder="Search"
aria-label="Search"
className={classnames(
'navbar__search-input',
{'search-bar-expanded': this.props.isSearchBarExpanded},
{'search-bar': !this.props.isSearchBarExpanded},
)}
onKeyPress={this.toggleSearchPressEnter}
/>
</div>
);
}
}
export default Search;