有没有可能在不渲染 HTML 的情况下使用 React?

我想知道是否可以使用 React 进行逻辑操作并将数据发送回 javascript 函数,而不用呈现任何 html。我考虑的组件是您传递一些数据到的组件,它将把数据发送回 response 之外的 javascript 函数。我知道这是可以做到的,而且我自己也做到了这一点,但是我不确定如果不按要求呈现 html,您将如何做到这一点。这是一个反应的实际用例吗?

66549 次浏览

As of React >= 16.2 it is possible to use any of these versions:

render() {
return false;
}


render() {
return null;
}


render() {
return [];
}


render() {
return <React.Fragment></React.Fragment>;
}


render() {
return <></>;
}

Returning undefined does not work.


The component I'm thinking of is something that you pass some data to, and it'll send data back to a javascript function outside of react.

Why would you want to create a component for that? Most of the time a regular js function in an existing component can be enough.

One usecase is for exemple to setup a side-effect when component is mounted and tear it down when it unmounts. For exemple if you have a ReactNative mobile app with portrait orientation, you could imagine a <Landscape/> component, that, when mounted, would allow temporarily to display the app in landscape orientation, and when unmounted, orientation would be reset to app default. You can surely manage this orientation change on an existing component, but creating a dedicated component might be more handy and reusable.

Note that React can also run on the server side so I guess it is possible to use it in such a way that it doesn't involve any DOM modifications (but maybe only the virtual DOM computation).

Just to clarify benno's comments. The ReactComponent.render method doc states:

You can also return null or false to indicate that you don't want anything rendered. Behind the scenes, React renders a <noscript> tag to work with our current diffing algorithm. When returning null or false, this.getDOMNode() will return null.

It is possible. react-router is an example of a library with components not rendering HTML. See https://github.com/rackt/react-router

This is the Route component of react-fouter with a render method returning false:


const Route = React.createClass({


statics: {
createRouteFromReactElement
},


propTypes: {
path: string,
component,
components,
getComponent: func,
getComponents: func
},


/* istanbul ignore next: sanity check */
render() {
invariant(
false,
'<Route> elements are for router configuration only and should not be rendered'
)
}


})

Yes it is very much possible and very much useful, in case of lazy loading components.

Consider this example with react-router.

import React from 'react'
import { Route, Link } from 'react-router-dom'


function asyncComponent(getComponent) {
return class AsyncComponent extends React.Component {
static Component = null;
state = { Component: AsyncComponent.Component };


componentWillMount() {
if (!this.state.Component) {
getComponent().then(Component => {
AsyncComponent.Component = Component
this.setState({ Component })
})
}
}
render() {
const { Component } = this.state
if (Component) {
return <Component {...this.props} />
}
return null
}
}
}


const Page1 = asyncComponent(() =>
System.import('./Page1.js').then(module => module.default)
)
const Page2 = asyncComponent(() =>
System.import('./Page2.js').then(module => module.default)
)
const Page3 = asyncComponent(() =>
System.import('./Page3.js').then(module => module.default)
)


const ParentComponent = () => (
<div>
<ul>
<li>
<Link to="/page1">Page1</Link>
</li>
<li>
<Link to="/page2">Page2</Link>
</li>
<li>
<Link to="/page3">Page3</Link>
</li>
</ul>
<div>
<Route path="/page1" component={Page1}/>
<Route path="/page2" component={Page2}/>
<Route path="/page3" component={Page3}/>
</div>
</div>
)