troyalford / react-jsx-parser Goto Github PK
View Code? Open in Web Editor NEWA React component which can parse JSX and output rendered React Components.
License: MIT License
A React component which can parse JSX and output rendered React Components.
License: MIT License
I'm getting the following warning:
Each child in an array or iterator should have a unique "key" prop.
Check the render method of `JsxParser`. See https://fb.me/react-warning-keys for more information.
in React.Fragment...
This issue is really similar to that one #83
Looks like the boolean values are not evaluated correctly.
jsx="(display 1: {true ? 1 : 0}); (display 0: {false ? 1 : 0})"
Actual:
(display 1: ); (display 0: )
Expected:
(display 1: 1); (display 0: 0)
I am getting the following error when I try to write a jest test case that utilizes the JsxParser component.
ReferenceError: Unknown plugin "transform-react-remove-prop-types" specified in "/.../node_modules/react-jsx-parser/.babelrc" at 2, attempted to resolve relative to "/.../node_modules/react-jsx-parser"
My jest configuration is using the default transformIgnorePatterns and is not specifying a transform property.
Dependencies:
"babel-jest": "21.2.0"
"jest": "21.2.1"
"react-jsx-parser": "1.3.4"
Reproduce code:
jsx='<span>{0}</span>'
The expected result is <span>0</span>
, but in fact it's <span></span>
.
I think it's cause by this
It appears I can't use arrays with this package. When I have the following code:
<JsxParser
bindings={{
Test: ["a", "b", "c"]
}}
components={{ Navigation }}
jsx={`
<div>
{Test[0]}
{Test.map(x => <p>{x}</p>)}
</div>
`}
/>
Nothing is rendered in the div. The map code causes a warning to occur:
Functions are not valid as a React child. This may happen if you return a Component instead of from render. Or maybe you meant to call this function rather than return it.
So I may have gotten the syntax wrong, or it may be because this package doesn't explicitly support incline functions. Either way, is there a way to use arrays with this package so I can output JSX for each element in an array?
Can i use function as a props, like this
<Tabs clickHandler={function => console.log('this is function')} widthTabItem={330} scrollable={true} classTabItem={'tab__item'} classHeadTab={'tab__head'} classTabContainer={'tab__container'} tabItems={tabItems} > {(num) => <span>{ num } </span> } </Tabs>
?
<script>
</script>
<div>
<ReactComponent />
</div>
or
<script>
</script>
<div>
<h1>Header</h1>
</div>
If I have a script tag in my html, then the React component or any other content does not get rendered.
Possibly the script tag is not being blacklisted.
My default props:
JsxParser.defaultProps = {
bindings: {}, // by default, do not add any additional bindings
// by default, just removes `on*` attributes (onClick, onChange, etc.)
// values are used as a regex to match property names
blacklistedAttrs: ['moduleTitle','elementId'], //= /on[a-z]*/gi
// by default, removes all <script> tags
blacklistedTags: ['script'],
//log errors
onError: (error) => {console.log("Error by JSX Parser: ", error)},
showWarnings: true,
// Components must extend React.Component, React.PureComponent, or be a Function
components: {},
jsx: '',
};
Hi I've been using react-jsx-parser
for days and it's been great till I tried to pass a custom function to the component that are passed as jsx template to the component.
Look at the code below:
<JsxParser
components={{
MyComponent
}}
jsx={
<MyComponent customName={'name'}
someObject={{name: 'foo',age: 25 }}
customFunction={(data)=>data.map(row=>row.name)}
/>}
/>
MyComponent
is rendering without problem and I can log and use customName
and someObject
easily inside the component but the custom function is always undefined
in any condition. Even when I pass a simple function like ()=>{}
it just does not recognize it, but I really need to pass some custom functions in order to make it as flexible as I can.
Any idea about that?
Thanks
Can I achieve this ?
<JsxParser
bindings={{ a: true }}
jsx={`
<div>{a && <span>Print this</span>}</div>
`}
/>
<MyFetch api='web.a.b'>
{(result) => ... }
</MyFetch>
anonymous function no running;
and
i tried to use binging = { callback: (result) => ... }
<MyFetch api='web.a.b'>
{callback}
</MyFetch>
but MyFetch props.children = [symbol, function, symbol]
I hope or the original MyFetch props.children = function
i must codeing
<MyFetch api='web.a.b'>{callback}</MyFetch>
It's impossible to use this library (v1.2.5 and above) with React 15.6.2, because this error is throwing:
Invariant Violation: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: symbol.
It seems to me that using of <React.Fragment> may to be a reason of it, because when i remove tags from sources in version 1.13.0 then it starts to work.
Here is the example to reproduce this problem.
If dump version to 1.2.4 or pump react version to 16.x.x then everything is works.
When I am trying to install this package it shows me this error
npm ERR! cb() never called!
I tried all possible workarounds that I could find. Also tried with 5 different machines (Both Mac and Linux) and it is giving me the same issue on all of them.
I'm seeing some weird effects when attempting to render a string that has a curly bracket in it. When attempting to render some code blocks, if I have a curly bracket that opens without closing on the same line, nothing will render. It's super weird.
Am I doing something wrong here?
<code>system {}</code>
Renders fine.
<code>system {</code>
Does not render at all.
The parser seems to replace non breaking spaces by normal spaces, I've tried using regular html entities, unicode characters, and hard-coding the non breaking spaces (typing alt + space on a Mac), no matter what I cannot get a non-breaking space in the parser output.
Compare the render of <JsxParser>
with React's dangerouslySetInnerHtml
prop using the following:
<p>This is a « test » without any non-breaking space</p>
<p>This is a «\u00a0test\u00a0» with non-breaking spaces as Unicode character</p>
<p>This is a « test » with non-breaking spaces as regular html entities</p>
You can also try with hard-coded non-breaking spaces but it seems I cannot type nor paste them in github's editor for some reason, so I didn't include this in the example input
With <JsxParser>
you should get regular spaces everywhere, with dangerouslySetInnerHtml
you should get the non-breaking spaces wherever you put them, which is the expected behavior.
I'm using React 15.6.1 and react-jsx-parser 1.1.5
The JsxParser fails to parse the following JSX-Code correctly:
<MyComponent prop1={{"key1": "value1", "key2": "value2"}} />
The resulting React component's value of prop1 will in this example be {undefined: "value2"}
.
I'm currently using react-jsx-parser
with output of the remark parser. I just wanted to let you know, that the application/html+xml
has more problems than expected.
It's pretty common that in html people forget to close tags like <img src='img.png' >
.
With application/html+xml
this result in all tags coming after that tag to be ignored.
What is your take on this? Should react-jsx-parser
be that strict?
For me unfortunately it's not an option as I can't rely on the html being compliant.
It would be nice if custom acorn plugin preferences could be passed as props so as to allow use of the allowNamespacedObjects
preference:
var ast = acorn.parse(code, {
plugins: {
jsx: { allowNamespacedObjects: true }
}
});
Having components
be an Array relies on those components having a .name
property, which will be mangled in any production setup (eg: uglify). Some people define a displayName
property on the constructor, which could make that technique more reliable.
I'd likely suggest it might be worth supporting the existing Array format alongside passing components
directly as an object. Here's an example of where the object is very useful:
<JsxParser components={{
// these classes wouldn't likely be named "A" or "IMG"
a: Link,
img: LazyImage
}} />
I'm creating a system that allows to use so-called blocks
. The blocks are wrapper for JSX templates fetched from internal API.
class Block extends React.Componenet {
components = getComponents();
data = getData(this.props.name);
template = getTemplate(this.props.name);
render() {
return (
<JsxParser
components={this.components}
jsx={this.template}
bindings={this.data}
renderInWrapper={false}
/>
);
}
}
I'd like to be able to build a document out of my blocks:
<Block name="todo-list">
{items.map((item) => <Block name="todo-item" key={item.id} todo={item} />)}
</Block>
What would be required to make the code above work? I'm happy to implement the required code for that feature. Would need some guidance 🙃
PS. I don't want to use bindings
to pass a mapping function 😉.
Hi, I've installed the npm package but I cannot import it. It throws the following error:
Cannot find module '../helpers/camelCase'
The same error here
I get the following error when I render JsxParser in my app:
warning.js:36 Warning: Failed prop type: components must contain only Subclasses of React.Component or React.PureComponent.
in t (at Message.js:48)
in Message (at Message.js:20)
in div (at decorators.js:26)
in div (created by View)
in View (at withChatContext.js:49)
in ChatContext(function View(){_classCallCheck(this,View);return _possibleConstructorReturn(this,(View.__proto__||Object.getPrototypeOf(View)).apply(this,arguments));}) (at decorators.js:19)
Not sure what this is about. Do other people get this?
I created a demo as bellow. But, when i clicked Button, onClick did not executed at all . Can you give me some suggestions ? Thanks (v1.13.0)
const MyComponent = () => (
<JsxParser
bindings={{
foo: "bar",
columns: JSX.fields,
onClick: function() {
alert("onClick Invoked");
}
}}
components={{ InjectableComponent, Button, Table }}
jsx={`
<h1>Test</h1>
<InjectableComponent onClick={onClick} />
<Button type="primary" onClick={onClick}>click{foo}</Button>
<Table columns={ columns } dataSource={[]}/>
`}
/>
);```
Hi Troy
We are trying to use the jsx-parser to enable end users interactively create their own controls 'on the fly' in a pseudo-language kind of way. What we are trying to avoid is them using plain HTML.
E.g. we want them to be able to use the parser as follows:
Admin input field:
<UserComponent>
<PersonComponent img={user.img} department={user.dep} ... />
<Button />
</UserComponent>
This would then render a user component based on the provided input above.
What we would not like to see is something like this:
<UserComponent>
<div>
<h1>SUPER USER</h1>
<img src="user.jpg" />
<a href='..'>CLICKME</a>
</div>
</UserComponent>
At the moment we could ban specific tags, but what we want to achieve is to ban all HTML tags.
For this I would like to see a prop that we can set to only allow using components, like so:
<JsxParser
bindings=...
jsx=...
components={{ InjectableComponent, UserComponent, PersonComponent, Button }}
componentsOnly={true}
/>
Within the parseElement function you could then check for something like this:
if(this.props.componentsOnly && !(name in components)) return undefined;
Let me know what you think. I can provide a pull request if you want.
-Sandro
Hi Troy
In your readme you refer using the jsx prop as follows:
jsx={`
<h1>Header</h1>
<InjectableComponent eventHandler={myEventHandler} />
`}
The carriage return as well as other whitespaces between every <tag>
(including components) however will break your code and nothing will be rendered.
I suggest removing all whitespaces between >< with a simple regex. E.g.:
.replace(/\>(\s|\n|\r|\t)*?\</g,"><")
If you want I can provide a pull request.
-Sandro
Hi, I’m seeing an issue that causes inline elements to butt up against each other in specific situations.
The following examples demonstrate the input string (passed to the jsx
prop) and the output HTML that is ultimately rendered. The example inputs are pure HTML as the issue is present even when no React components are injected.
In this example, the output is correct:
Input
a b <strong>c</strong> <em>d</em>
Output
<div class="jsx-parser">a b <strong>c</strong> <em>d</em></div>
However in this example, the output is incorrect (c
and d
have no space between them):
Input
<p>a b</p>
<p><strong>c</strong> <em>d</em></p>
Output
<div class="jsx-parser"><p>a b</p>
<p><strong>c</strong><em>d</em></p></div>
I’ve tested this with renderInWrapper
both being true
and false
with the same results.
I am trying to inject a value into {this.props.test}
and it returns empty/blank. See the following snippet.
<JsxParser
bindings={{test: 'this is a test'}}
jsx={'<h1>test</h1><p>seriously {this.props.test}</p>'} />
Am I misunderstanding or this is out of the scope of this project?
I was expecting output similar to the following.
<h1>test</h1>
<p>seriously this is a test</p>
But I get:
<h1>test</h1>
<p>seriously </p>
Thanks for your attention!
https://www.npmjs.com/package/react-jsx-parser contains no link to the URL of the GitHub repository.
Compare with https://www.npmjs.com/package/react ("repository" link)
When a new version for react-jsx-parser
is published (npm outdated
), when I google I usually only find the listing on npmjs.com, and this unfortunately contains no changelog.
Hi, I'm trying to pass something like
<pre><code class="markdown"># hello
a paragraph
</code></pre>
But instead of rendering nicely, the result is actually
<pre><code class=""><undefined># hello a paragraph</undefined></code></pre>
Is this a bug or am I doing something wrong?
If you do pass some components to JsxParser, then they have to be in the jsx input, otherwise JsxParser will trigger an error and the output will be empty.
I do have a single page webapp built with React and React-router. A lot of my app pages depends on dynamic html content that is stored across a bunch of json files, that are loaded depending on the route.
The html content can of course have <a>
html tags, but it's not always the case.
Those links are the reason I started using JsxParser
: given my json object, I can replace <a>
tags with some custom wrapper built on-top of React-router's <Link>
component. This way I can have dynamic content within my app and still benefit of the router's functionality so the whole page doesn't refresh whenever the user clicks on an internal link that would have been within the html content.
Whenever my html had links JsxParser
would happily process it and create the React components, but the situation is different when there is no link in the input, JsxParser would then trigger an error.
The workaround for me was to conditionally use either JsxParser
or React dangerouslySetInnetHtml
prop based on wether or my html content had some links. It's not really complicated to do, but I was thinking this use-case should be pretty common, and if there's an easy way to make those custom components optional in JsxParser, it would make it even easier to use.
This way you could use out of the box something like:
<JsxParser
components={{
Link
}}
jsx={loadedHtml}
/>
Without even having to think about wether or not your loadedHtml
has links or not. It wasn't really clear tom me after reading the README, so maybe it's worth mentioning about this.
Is there a way to have jsx not render in an <div class="jsx-parser">
?
Hi Troy
I noticed that manipulating bindings via state do not reflect when the JsxParser component is rerendered. It looks like this is a by-design behaviour, since you do not handle new bindings as you handle blacklistedTags, blacklistedAttr and Jsx. Is there a possible reason for that?
If so I would like to show you an akward behaviour that should be handled. Consider the following code:
class TitleComponent extends React.Component<any, any> {
public render() {
return(
<h1>{this.props.text}</h1>
);
}
}
export class DynamicComponent extends React.Component<any, any> {
constructor(props) {
super(props);
this.state = {text: "SOMETHING"};
// change state 1
setTimeout(() => {
this.setState(previousState => {
console.log("change state 1");
return { text: "FIRST TITLE" };
});
}, 2000);
// change state 2
setTimeout(() => {
this.setState(previousState => {
console.log("change state 2");
return { text: "SECOND TITLE" };
});
}, 4000);
}
public render() {
let textState = this.state.text;
// only showing 'FIRST TITLE' after (4 sec)
return(
<JsxParser
bindings={{textState}}
components={{ TitleComponent }}
jsx={`<TitleComponent text={textState}/>`}
/>
);
}
}
This code is not working like expected, since the title component only gets updated after the second state change - however - showing 'FIRST TITLE' which was the props.binding object from the frist change.
This could be fixed changing those two lines:
handleNewProps = (props) => {
...
this.bindings = (props.bindings || {})
...
}
...
parseExpression = (expression) => {
switch (expression.type) {
...
case 'Identifier':
return this.bindings[expression.name] || undefined
...
}
}
Regards,
Sandro
Hello,
Thank you so much for this wonderful library!
Can I know how to use default events like onSubmit using this library, I am trying to use it this way but I think I am going in the wrong direction.
HTML:
<form onSubmit={eventHandler}>
<h1>Login</h1>
<label>Username</label>
<input required type="text" name="username" />
<label>Password</label>
<input required type="password" name="password" />
<button>Login</button>
</form>
// Loading HTML dynamically like this
const dynamicHtml = loadRemoteData()
...
<JsxParser bindings={{
eventHandler : (e) => {
e.preventDefault();
console.log('clicked');
// stuff to do
}
}}
jsx={dynamicHtml} />
The data is loading properly and form is working but it is unable to discover the event onSubmit.
Thank you in advance!
Found this via preact-markup. Awsome! Does this also work for Server Side Rendering?
As reported in the comments of #18, tags which have non-explicit values aren't currently working correctly.
Example:
<MyComponent readOnly />
The above JSX should result in rendering the MyComponent
object with props: { readOnly: true }
- and instead, it omits readOnly
from the props entirely.
version 1.3.1
<JsxParser
bindings={{
testClick: (a, b) => {
console.log(a, b)
}
}}
blacklistedAttrs={[]}
jsx={`
<div onClick={testClick('a', 'b')}>test click</div>
<div onClick={testClick.bind('a', 'b')}>test click</div>
`}
></JsxParser>
how function.testClick use params ??
ReferenceError: window is not defined
at Object.<anonymous> (/node_modules/react-jsx-parser/lib/react-jsx-parser.min.js:1:285)
at Module._compile (internal/modules/cjs/loader.js:702:30)
Happens when updating react-jsx-parser 1.3.2 → 1.3.4
There seems to be a new dependency to window
- is it still possible to use the latest version on server-side?
After switching from application/json
for the DOMParser.parseFromString()
MIME type to html/text
, one unfortunate side-effect is that the parsing algorithm now reports the nodeName
of all nodes in UPPERCASE
.
Thus, if a user had 2 classes, TreeView
and Treeview
, passed in as components=[TreeView, Treeview]
, the parser would use the 2nd instance in both cases.
I don't think this is a likely problem for folks - and would be easily solvable by simply renaming the second component (TreeView2
for instance) - but it's worth noting/tracking.
Hello.
Thank you for the work on this library.
I can't seem to get template strings work.
<JsxParser
bindings={{ key: 'fi' }}
jsx={
'<div><img src={`https://cdn.jsdelivr.net/gh/hjnilsson/country-flags/svg/${key}.svg`} /></div>'
}
/>
When observed in the dev tools, just <img>
appears.
In comparison,
<JsxParser
jsx={
'<div><img src={"https://cdn.jsdelivr.net/gh/hjnilsson/country-flags/svg/fi.svg"} /></div>'
}
/>
This works, in that src
attributes appears correctly. I'd like to interpolate a binding though.
<JsxParser
components={{ Link }}
jsx={'\
<h1>Header</h1>\
<Link to="/this">Yes</Link>\
'}
/>
This parses to -
<div class="jsx-parser">
<h1>Header</h1>
<!-- react-text: 314 -->
<!-- /react-text -->
<a href="/this"></a>
</div>
The string "Yes" passed as the children of the React Component Link
is ignored.
Is it intentional or a bug or yet to be added?
After switching from application/xml
based parsing to text/html
parsing, one of the side-effects is that the typical <Component />
syntax no longer works consistently.
When rendering something like:
<Component />
<div>Text</div>
... the DOMParser
will automatically rewrite to
<Component>
<div>Text</div>
</Component>
...because custom void elements are not allowed by HTML5.
This is pretty annoying, tbh, from a usability standpoint - but the easiest alternative is to parse as application/xml
- which causes several other issues. The biggest of these is that valid void elements, such as <img>
wind up being treated as invalid XML - and all sorts of strange "corrections" are made to the rendered DOM as a result, prior to actual processing/parsing.
For now, the tradeoff I'm sticking with is to stick with text/html
parsing - because then at least the corrections to DOM are more intuitive, as they match the corrections the browser is already making. (Adding <tbody>
around <tr>
and such.)
In the future - maybe it would make sense to do some additional pre-parsing and attempt to apply corrections to the raw HTML/XML string prior to DOMParser
getting ahold of it - or using some other type of parser... but for the moment, I don't want to expand the footprint and complexity of the component simply to avoid closing tags.
it not shown the state, I want it because want the code will be dynamically
const MyComponent = () => (
<JsxParser
bindings={}
components={{ }}
jsx={
//textarea will onchange on this.state.form and parse the data in textarea
this.state.form
}
/>
)
//Input in textarea
<div>{this.state.test}</div>
Hi, does react-jsx-parser
currently support unary operator negation i.e. something like -75 as the value for a prop in its output components?
I am currently using react-jsx-parser
to take in a string of JSX to output a series of React components. I'm passing this string of JSX as content
in jsx={content}
for JsxParser.
One of my components takes a prop called min
which must be a number (can be a negative number). So when I pass in min={75}
into this component, react-jsx-parser correctly passes the prop through to the component with the value 75. But when I pass in min={-75}
, react-jsx-parser produces undefined
as the value for the min
prop.
The culprit, I believe, may be the switch statement on Line 46 of react-jsx-parser/source/components/JsxParser.js
where the default returns undefined
.
Please kindly advise and/or suggest a workaround, or am I possibly using react-jsx-parser
wrong?
Thank you.
Input will lost focus when we key in.
export default class ParentComponet extends React.PureComponent {
constructor(props) {
super(props)
this.handleChange = this.handleChange.bind(this)
this.state = {value: '1'}
}
handleChange(event) {
this.setState({
value: event.target.value
})
}
render() {
return (
<JsxParser
bindings={{
value: this.state.value,
handleChange: this.handleChange,
}}
components={{}}
jsx={"<input type='text' value={value} onChange={handleChange} />"}/>
)
}
}
how can i avoid this?
Is there any way to catch unrecognized tags with onError?
Example: https://codesandbox.io/s/l5pj34jk5z
Error: Warning: The tag <failure> is unrecognized in this browser. If you meant to render a React component, start its name with an uppercase letter.
Is this the expected behavior?
Hi Troy, great project. One question, from looking at the code it seems as if react-jsx-parser doesn't support embedded Javascript expressions. Is this correct?
Am using react-jsx-parser for converting html/xml data in react js element. Only issue am facing is while passing some object data . Its is converted into string.
Example :
"<customElement data=['1','2','3']>"
For above component if I use the parser then it is returning the props data as string ..
how can i do somthing like this
<JsxParser bindings={{ className: classes.root, ...props }} components={{CurrencyLastUpdated}} jsx={'<div className={className} {...props}>test</div>'} />
First, nice project.
It worked fine util I added ListItemIcon:
<JsxParser components={{ List, ListItem, ListItemIcon, ListItemText, InboxIcon }} jsx={ '<ListItem button><ListItemIcon> <InboxIcon /></ListItemIcon><ListItemText primary="Dashboard" /> </ListItem> ' } />
Error:
Uncaught TypeError: Cannot read property 'className' of undefined
at ListItemIcon (ListItemIcon.js:58)
at createEagerElementUtil (createEagerElementUtil.js:18)
at createEagerFactory.js:18
at Style.render (withStyles.js:324)
at ReactCompositeComponent.js:795
at measureLifeCyclePerf (ReactCompositeComponent.js:75)
at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (ReactCompositeComponent.js:794)
at ReactCompositeComponentWrapper._renderValidatedComponent (ReactCompositeComponent.js:821)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:361)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:257)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.