我第一次使用 React.js,找不到通过点击事件在页面上显示或隐藏某些内容的方法。我没有将任何其他库加载到页面中,因此我正在寻找使用 React 库的本地方式。这就是我到目前为止所拥有的。我想在点击事件触发时显示结果 div。
var Search= React.createClass({
handleClick: function (event) {
console.log(this.prop);
},
render: function () {
return (
<div className="date-range">
<input type="submit" value="Search" onClick={this.handleClick} />
</div>
);
}
});
var Results = React.createClass({
render: function () {
return (
<div id="results" className="search-results">
Some Results
</div>
);
}
});
React.renderComponent(<Search /> , document.body);
大约在 2020 年做出反应
在 onClick
回调中,调用 state hook's setter 函数来更新状态并重新渲染:
const Search = () => { const [showResults, setShowResults] = React.useState(false) const onClick = () => setShowResults(true) return (
大约 2014 年的反应
关键是使用 setState
在点击处理程序中更新组件的状态。当状态更改被应用时,render
方法被再次调用并使用新状态:
var Search = React.createClass({ getInitialState: function() { return { showResults: false }; }, onClick: function() { this.setState({ showResults: true }); }, render: function() { return (
<style type="text/css">
.hidden { display:none; }
</style>
const Example = props =>
<div className={props.shouldHide? 'hidden' : undefined}>Hello</div>
这是三元运算符的另一种语法:
{ this.state.showMyComponent ? <MyComponent /> : null }
相当于:
{ this.state.showMyComponent && <MyComponent /> }
还有 display: 'none';
的替代语法
<MyComponent style={this.state.showMyComponent ? {} : { display: 'none' }} />
但是,如果您过度使用 display: 'none'
,这会导致 DOM 污染并最终减慢您的应用程序。
!!
即 { !!this.state.myComponents.length && <MyComponent /> }
转换为布尔值
这是我的方法。
import React, { useState } from 'react';
function ToggleBox({ title, children }) {
const [isOpened, setIsOpened] = useState(false);
function toggle() {
setIsOpened(wasOpened => !wasOpened);
}
return (
<div className="box">
<div className="boxTitle" onClick={toggle}>
{title}
</div>
{isOpened && (
<div className="boxContent">
{children}
</div>
)}
</div>
);
}
在上面的代码中,为了实现这一点,我使用如下代码:
{opened && <SomeElement />}
只有当 opened
为真时才会呈现 SomeElement
。它之所以起作用,是因为 JavaScript 解析逻辑条件的方式:
true && true && 2; // will output 2
true && false && 2; // will output false
true && 'some string'; // will output 'some string'
opened && <SomeElement />; // will output SomeElement if `opened` is true, will output false otherwise (and false will be ignored by react during rendering)
// be careful with 'falsy' values eg
const someValue = [];
someValue.length && <SomeElement /> // will output 0, which will be rednered by react
// it'll be better to:
someValue.length > 0 && <SomeElement /> // will render nothing as we cast the value to boolean
使用这种方法而不是 CSS 'display: none' 的原因;
虽然使用 CSS 隐藏元素可能“更便宜”——在这种情况下,“隐藏”元素在反应世界中仍然“活跃”(这可能使其实际上更加昂贵),这意味着如果父元素的道具(例如.
这意味着如果父元素的道具(例如
隐藏元素可能仍在运行一些生命周期方法 - 例如。它可能会在每次更新后从服务器获取一些数据,即使它不可见
如果隐藏的元素接收到不正确的数据,它可能会导致应用程序崩溃。这可能会发生,因为您可以在更新状态时“忘记”不可见的节点
在使元素可见时,您可能会错误地设置错误的“显示”样式 - 例如。某些 div 默认为 'display: flex',但您会错误地将 'display: block' 设置为 display: invisible ? 'block' : 'none' 这可能会破坏布局
使用 someBoolean &&
在许多情况下,您希望在元素状态重新出现时“重置”它。例如。您可能有一个滑块,每次显示时都希望将其设置为初始位置。 (如果这是保持先前元素状态的理想行为,即使它是隐藏的,这在 IMO 中很少见——如果以不同的方式记住这个状态会很复杂,我确实会考虑使用 CSS)
this.setState({isOpened: !isOpened});
。当你修改状态时,不要依赖状态本身。这是一个很好的例子:reactjs.org/docs/… 所以它应该是:this.setState( s => ({isOpened: !s.isOpened}) )
。注意 setState 中的箭头函数。
使用最新版本的 react 0.11,您也可以只返回 null 以不呈现任何内容。
这是利用虚拟 DOM 的好方法:
class Toggle extends React.Component {
state = {
show: true,
}
toggle = () => this.setState((currentState) => ({show: !currentState.show}));
render() {
return (
<div>
<button onClick={this.toggle}>
toggle: {this.state.show ? 'show' : 'hide'}
</button>
{this.state.show && <div>Hi there</div>}
</div>
);
}
}
示例 here
使用 React 钩子:
const Toggle = () => {
const [show, toggleShow] = React.useState(true);
return (
<div>
<button
onClick={() => toggleShow(!show)}
>
toggle: {show ? 'show' : 'hide'}
</button>
{show && <div>Hi there</div>}
</div>
)
}
示例 here
我为您创建了一个小组件来处理这个问题:react-toggle-display
它根据 hide
或 show
属性将样式属性设置为 display: none !important
。
示例用法:
var ToggleDisplay = require('react-toggle-display');
var Search = React.createClass({
getInitialState: function() {
return { showResults: false };
},
onClick: function() {
this.setState({ showResults: true });
},
render: function() {
return (
<div>
<input type="submit" value="Search" onClick={this.onClick} />
<ToggleDisplay show={this.state.showResults}>
<Results />
</ToggleDisplay>
</div>
);
}
});
var Results = React.createClass({
render: function() {
return (
<div id="results" className="search-results">
Some Results
</div>
);
}
});
React.renderComponent(<Search />, document.body);
已经有几个很好的答案,但我认为它们没有得到很好的解释,并且给出的几种方法包含一些可能会绊倒人们的陷阱。因此,我将介绍三种主要方式(外加一个题外话选项)并解释其优缺点。我之所以写这篇文章,主要是因为很多人推荐了选项 1,如果使用不当,该选项会出现很多潜在问题。
选项 1:父级中的条件渲染。
我不喜欢这种方法,除非您只打算渲染一次组件并将其留在那里。问题是每次切换可见性时都会导致从头开始创建组件的反应。这是示例。 LogoutButton 或 LoginButton 在父 LoginControl 中有条件地呈现。如果你运行它,你会注意到构造函数在每次按钮点击时被调用。 https://codepen.io/Kelnor/pen/LzPdpN?editors=1111
class LoginControl extends React.Component {
constructor(props) {
super(props);
this.handleLoginClick = this.handleLoginClick.bind(this);
this.handleLogoutClick = this.handleLogoutClick.bind(this);
this.state = {isLoggedIn: false};
}
handleLoginClick() {
this.setState({isLoggedIn: true});
}
handleLogoutClick() {
this.setState({isLoggedIn: false});
}
render() {
const isLoggedIn = this.state.isLoggedIn;
let button = null;
if (isLoggedIn) {
button = <LogoutButton onClick={this.handleLogoutClick} />;
} else {
button = <LoginButton onClick={this.handleLoginClick} />;
}
return (
<div>
<Greeting isLoggedIn={isLoggedIn} />
{button}
</div>
);
}
}
class LogoutButton extends React.Component{
constructor(props, context){
super(props, context)
console.log('created logout button');
}
render(){
return (
<button onClick={this.props.onClick}>
Logout
</button>
);
}
}
class LoginButton extends React.Component{
constructor(props, context){
super(props, context)
console.log('created login button');
}
render(){
return (
<button onClick={this.props.onClick}>
Login
</button>
);
}
}
function UserGreeting(props) {
return <h1>Welcome back!</h1>;
}
function GuestGreeting(props) {
return <h1>Please sign up.</h1>;
}
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
}
ReactDOM.render(
<LoginControl />,
document.getElementById('root')
);
现在 React 在从头开始创建组件方面非常快。但是,它仍然必须在创建它时调用您的代码。因此,如果您的构造函数、componentDidMount、render 等代码很昂贵,那么它会显着减慢组件的显示速度。这也意味着您不能将它与您希望在隐藏时保留状态(并在显示时恢复)的有状态组件一起使用。一个优点是隐藏组件在被选中之前根本不会创建。因此隐藏组件不会延迟您的初始页面加载。在某些情况下,您可能希望在切换时重置有状态组件。在这种情况下,这是您的最佳选择。
选项 2:子项中的条件渲染
这将创建两个组件一次。如果组件被隐藏,则将其余的渲染代码短路。您还可以使用 visible 道具在其他方法中短路其他逻辑。注意 codepen 页面中的 console.log。 https://codepen.io/Kelnor/pen/YrKaWZ?editors=0011
class LoginControl extends React.Component {
constructor(props) {
super(props);
this.handleLoginClick = this.handleLoginClick.bind(this);
this.handleLogoutClick = this.handleLogoutClick.bind(this);
this.state = {isLoggedIn: false};
}
handleLoginClick() {
this.setState({isLoggedIn: true});
}
handleLogoutClick() {
this.setState({isLoggedIn: false});
}
render() {
const isLoggedIn = this.state.isLoggedIn;
return (
<div>
<Greeting isLoggedIn={isLoggedIn} />
<LoginButton isLoggedIn={isLoggedIn} onClick={this.handleLoginClick}/>
<LogoutButton isLoggedIn={isLoggedIn} onClick={this.handleLogoutClick}/>
</div>
);
}
}
class LogoutButton extends React.Component{
constructor(props, context){
super(props, context)
console.log('created logout button');
}
render(){
if(!this.props.isLoggedIn){
return null;
}
return (
<button onClick={this.props.onClick}>
Logout
</button>
);
}
}
class LoginButton extends React.Component{
constructor(props, context){
super(props, context)
console.log('created login button');
}
render(){
if(this.props.isLoggedIn){
return null;
}
return (
<button onClick={this.props.onClick}>
Login
</button>
);
}
}
function UserGreeting(props) {
return <h1>Welcome back!</h1>;
}
function GuestGreeting(props) {
return <h1>Please sign up.</h1>;
}
function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return <UserGreeting />;
}
return <GuestGreeting />;
}
ReactDOM.render(
<LoginControl />,
document.getElementById('root')
);
现在,如果初始化逻辑很快并且子节点是无状态的,那么您将不会看到性能或功能上的差异。但是,为什么要让 React 每次切换都创建一个全新的组件呢?但是,如果初始化成本很高,则每次切换组件时选项 1 都会运行它,这会在切换时减慢页面速度。选项 2 将在第一页加载时运行所有组件的初始化。减慢第一个负载。应再次注意。如果您只是根据条件显示组件一次而不切换它,或者您希望它在切换时重置,那么选项 1 很好,可能是最好的选择。
但是,如果页面加载缓慢是一个问题,则意味着您在生命周期方法中拥有昂贵的代码,这通常不是一个好主意。您可以并且可能应该通过将昂贵的代码移出生命周期方法来解决页面加载缓慢的问题。将其移至由 ComponentDidMount 启动的异步函数,并让回调将其放入带有 setState() 的状态变量中。如果状态变量为 null 并且组件可见,则让渲染函数返回一个占位符。否则渲染数据。这样,页面将快速加载并在加载时填充选项卡。您还可以将逻辑移动到父级并将结果作为道具推送给子级。这样,您可以优先考虑首先加载哪些选项卡。或者缓存结果并仅在第一次显示组件时运行逻辑。
选项 3:类隐藏
类隐藏可能是最容易实现的。如前所述,您只需创建一个带有 display: none 的 CSS 类并根据 prop 分配该类。缺点是调用每个隐藏组件的整个代码,并且所有隐藏组件都附加到 DOM。 (选项 1 根本不创建隐藏的组件。选项 2 在隐藏组件时会缩短不必要的代码并从 DOM 中完全删除组件。)根据评论者所做的一些测试,这似乎在切换可见性方面更快其他答案,但我不能说。
选项 4:一个组件但更改道具。或者可能根本没有组件并缓存 HTML。
这个不适用于每个应用程序,并且它不是主题,因为它不是隐藏组件,但对于某些用例来说,它可能是比隐藏更好的解决方案。假设您有标签。可以编写一个 React 组件,然后使用道具来更改选项卡中显示的内容。您还可以将 JSX 保存到状态变量中,并使用 prop 来决定在渲染函数中返回哪个 JSX。如果必须生成 JSX,则执行此操作并将其缓存在父级中,并将正确的一个作为道具发送。或者在child中生成并缓存在child的状态中,并使用props选择活动的。
您在状态中设置一个布尔值(例如“显示”),然后执行以下操作:
var style = {};
if (!this.state.show) {
style.display = 'none'
}
return <div style={style}>...</div>
使用 Hooks 在 React 中显示/隐藏元素的简单方法
const [showText, setShowText] = useState(false);
现在,让我们为我们的渲染方法添加一些逻辑:
{showText && <div>This text will show!</div>}
和
onClick={() => setShowText(!showText)}
好工作。
使用 React Hooks 的简单隐藏/显示示例:(请不要提琴)
const Example = () => {
const [show, setShow] = useState(false);
return (
<div>
<p>Show state: {show}</p>
{show ? (
<p>You can see me!</p>
) : null}
<button onClick={() => setShow(!show)}>
</div>
);
};
export default Example;
我能够使用css属性“隐藏”。不知道可能的缺点。
export default function App() {
const [hidden, setHidden] = useState(false);
return (
<div>
<button onClick={() => setHidden(!hidden)}>HIDE</button>
<div hidden={hidden}>hidden component</div>
</div>
);
}
class FormPage extends React.Component{
constructor(props){
super(props);
this.state = {
hidediv: false
}
}
handleClick = (){
this.setState({
hidediv: true
});
}
render(){
return(
<div>
<div className="date-range" hidden = {this.state.hidediv}>
<input type="submit" value="Search" onClick={this.handleClick} />
</div>
<div id="results" className="search-results" hidden = {!this.state.hidediv}>
Some Results
</div>
</div>
);
}
}
我从 React 团队的声明开始:
在 React 中,您可以创建不同的组件来封装您需要的行为。然后,您可以只渲染其中的一部分,具体取决于您的应用程序的状态。 React 中条件渲染的工作方式与 JavaScript 中条件的工作方式相同。使用 if 或条件运算符等 JavaScript 运算符创建表示当前状态的元素,并让 React 更新 UI 以匹配它们。
您基本上需要在单击按钮时显示组件,您可以通过两种方式进行操作,使用纯 React 或使用 CSS,使用纯 React 方式,您可以在您的案例中执行类似以下代码的操作,因此在第一次运行时,结果没有显示为 hideResults
是 true
,但是通过单击按钮,状态会发生变化并且 hideResults
是 false
并且组件会以新的值条件再次呈现,这是更改组件的非常常见的用法在 React 中查看...
var Search = React.createClass({
getInitialState: function() {
return { hideResults: true };
},
handleClick: function() {
this.setState({ hideResults: false });
},
render: function() {
return (
<div>
<input type="submit" value="Search" onClick={this.handleClick} />
{ !this.state.hideResults && <Results /> }
</div> );
}
});
var Results = React.createClass({
render: function() {
return (
<div id="results" className="search-results">
Some Results
</div>);
}
});
ReactDOM.render(<Search />, document.body);
如果您想进一步研究 React 中的条件渲染,请查看 here。
class Toggle extends React.Component {
state = {
show: true,
}
render() {
const {show} = this.state;
return (
<div>
<button onClick={()=> this.setState({show: !show })}>
toggle: {show ? 'show' : 'hide'}
</button>
{show && <div>Hi there</div>}
</div>
);
}
}
如果您想了解如何切换组件的显示,请查看此小提琴。
http://jsfiddle.net/mnoster/kb3gN/16387/
var Search = React.createClass({
getInitialState: function() {
return {
shouldHide:false
};
},
onClick: function() {
console.log("onclick");
if(!this.state.shouldHide){
this.setState({
shouldHide: true
})
}else{
this.setState({
shouldHide: false
})
}
},
render: function() {
return (
<div>
<button onClick={this.onClick}>click me</button>
<p className={this.state.shouldHide ? 'hidden' : ''} >yoyoyoyoyo</p>
</div>
);
}
});
ReactDOM.render( <Search /> , document.getElementById('container'));
使用 ref 并操作 CSS
一种方法是使用 React 的 ref
并使用浏览器的 API 操作 CSS 类。如果唯一的目的是在单击按钮时隐藏/显示某些 DOM 元素,它的好处是避免在 React 中重新渲染。
// Parent.jsx
import React, { Component } from 'react'
export default class Parent extends Component {
constructor () {
this.childContainer = React.createRef()
}
toggleChild = () => {
this.childContainer.current.classList.toggle('hidden')
}
render () {
return (
...
<button onClick={this.toggleChild}>Toggle Child</button>
<div ref={this.childContainer}>
<SomeChildComponent/>
</div>
...
);
}
}
// styles.css
.hidden {
display: none;
}
PS如果我错了,请纠正我。 :)
在某些情况下,高阶组件可能有用:
创建高阶组件:
export var HidableComponent = (ComposedComponent) => class extends React.Component {
render() {
if ((this.props.shouldHide!=null && this.props.shouldHide()) || this.props.hidden)
return null;
return <ComposedComponent {...this.props} />;
}
};
扩展您自己的组件:
export const MyComp= HidableComponent(MyCompBasic);
然后你可以像这样使用它:
<MyComp hidden={true} ... />
<MyComp shouldHide={this.props.useSomeFunctionHere} ... />
这减少了一些样板文件并强制遵守命名约定,但是请注意 MyComp 仍将被实例化 - 前面提到了省略的方法:
{ !hidden && <MyComp ... /> }
如果你使用 bootstrap 4,你可以这样隐藏元素
className={this.state.hideElement ? "invisible" : "visible"}
使用 rc-if-else 模块
npm install --save rc-if-else
import React from 'react';
import { If } from 'rc-if-else';
class App extends React.Component {
render() {
return (
<If condition={this.props.showResult}>
Some Results
</If>
);
}
}
使用这种简洁而简短的语法:
{ this.state.show && <MyCustomComponent /> }
这是一个简单、有效和最佳的解决方案,它带有一个用于显示/隐藏元素的无类 React 组件。使用 React-Hooks,它在使用 React 16 的最新 create-react-app 项目中可用
import React, {useState} from 'react';
function RenderPara(){
const [showDetail,setShowDetail] = useState(false);
const handleToggle = () => setShowDetail(!showDetail);
return (
<React.Fragment>
<h3>
Hiding some stuffs
</h3>
<button onClick={handleToggle}>Toggle View</button>
{showDetail && <p>
There are lot of other stuffs too
</p>}
</React.Fragment>)
}
export default RenderPara;
快乐编码:)
//use ternary condition
{ this.state.yourState ? <MyComponent /> : null }
{ this.state.yourState && <MyComponent /> }
{ this.state.yourState == 'string' ? <MyComponent /> : ''}
{ this.state.yourState == 'string' && <MyComponent /> }
//Normal condition
if(this.state.yourState){
return <MyComponent />
}else{
return null;
}
<button onClick={()=>this.setState({yourState: !this.props.yourState}>Toggle View</button>
只需找出一种新的神奇方式使用(useReducer)功能组件
const [state, handleChangeState] = useReducer((state) => !state, false);改变状态
这也可以这样实现(非常简单的方法)
class app extends Component {
state = {
show: false
};
toggle= () => {
var res = this.state.show;
this.setState({ show: !res });
};
render() {
return(
<button onClick={ this.toggle }> Toggle </button>
{
this.state.show ? (<div> HELLO </div>) : null
}
);
}
此示例展示了如何使用每 1 秒切换一次的切换开关在组件之间切换
import React ,{Fragment,Component} from "react";
import ReactDOM from "react-dom";
import "./styles.css";
const Component1 = () =>(
<div>
<img
src="https://i.pinimg.com/originals/58/df/1d/58df1d8bf372ade04781b8d4b2549ee6.jpg" />
</div>
)
const Component2 = () => {
return (
<div>
<img
src="http://www.chinabuddhismencyclopedia.com/en/images/thumb/2/2e/12ccse.jpg/250px-
12ccse.jpg" />
</div>
)
}
class App extends Component {
constructor(props) {
super(props);
this.state = {
toggleFlag:false
}
}
timer=()=> {
this.setState({toggleFlag:!this.state.toggleFlag})
}
componentDidMount() {
setInterval(this.timer, 1000);
}
render(){
let { toggleFlag} = this.state
return (
<Fragment>
{toggleFlag ? <Component1 /> : <Component2 />}
</Fragment>
)
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
状态和效果的应用已经并且必须封装在同一个组件中,因此,没有什么比创建自定义组件作为钩子来解决在这种情况下是否使特定块或元素可见或不可见更好的了。
// hooks/useOnScreen.js
import { useState, useEffect } from "react"
const useOnScreen = (ref, rootMargin = "0px") => {
const [isVisible, setIsVisible] = useState(false)
useEffect(() => {
const observer = new IntersectionObserver(
([entry]) => {
setIsVisible(entry.isIntersecting)
},
{
rootMargin
}
);
const currentElement = ref?.current
if (currentElement) {
observer.observe(currentElement)
}
return () => {
observer.unobserve(currentElement)
}
}, [])
return isVisible
}
export default useOnScreen
然后自定义钩子嵌入到组件内部
import React, { useRef } from "react";
import useOnScreen from "hooks/useOnScreen";
const MyPage = () => {
const ref = useRef(null)
const isVisible = useOnScreen(ref)
const onClick = () => {
console.log("isVisible", isVisible)
}
return (
<div ref={ref}>
<p isVisible={isVisible}>
Something is visible
</p>
<a
href="#"
onClick={(e) => {
e.preventDefault();
onClick(onClick)
}}
>
Review
</a>
</div>
)
}
export default MyPage
由 useRef 钩子控制的 ref 变量允许我们捕获我们想要控制的块在 DOM 中的位置,然后由 useOnScreen 钩子控制的 isVisible 变量允许我们通过useRef 钩子。我相信 useState、useEfect 和 useRef 钩子的这种实现允许您通过使用自定义钩子分隔它们来避免组件渲染。
希望这些知识对你有用。
// Try this way
class App extends Component{
state = {
isActive:false
}
showHandler = ()=>{
this.setState({
isActive: true
})
}
hideHandler = () =>{
this.setState({
isActive: false
})
}
render(){
return(
<div>
{this.state.isActive ? <h1>Hello React jS</h1> : null }
<button onClick={this.showHandler}>Show</button>
<button onClick={this.hideHandler}>Hide</button>
</div>
)
}
}
var Search= React.createClass({
getInitialState: () => { showResults: false },
onClick: () => this.setState({ showResults: true }),
render: function () {
const { showResults } = this.state;
return (
<div className="date-range">
<input type="submit" value="Search" onClick={this.handleClick} />
{showResults && <Results />}
</div>
);
}
});
var Results = React.createClass({
render: function () {
return (
<div id="results" className="search-results">
Some Results
</div>
);
}
});
React.renderComponent(<Search /> , document.body);
不定期副业成功案例分享
{ showResults ? <Results /> : null }
可以做{ showResults && <Results /> }