Skip to content

Commit

Permalink
Merge branch 'master' into prateekbh/suspense-hydration
Browse files Browse the repository at this point in the history
  • Loading branch information
developit committed Jan 27, 2020
2 parents 0a87ce7 + a6cab5b commit eca2cf2
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 9 deletions.
8 changes: 8 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,14 @@ In the end there is no effect on size regardless if you use `const`, `let` or us

This will only become important once shipping modern JavaScript code on npm becomes a thing and bundlers follow suit.

## How to create a good bug report

To be able to fix issues we need to see them on our machine. This is only possible when we can reproduce the error. The easiest way to do that is narrow down the problem to specific components or combination of them. This can be done by removing as much unrelated code as possible.

The perfect way to do that is to make a [codesandbox](https://codesandbox.io/). That way you can easily share the problematic code and ensure that others can see the same issue you are seeing.

For us a [codesandbox](https://codesandbox.io/) says more than a 1000 words :tada:

## I have more questions on how to contribute to Preact. How can I reach you?

We closely watch our issues and have a pretty active [Slack workspace](https://preact-slack.now.sh/). Nearly all our communication happens via these two forms of communication.
Expand Down
14 changes: 7 additions & 7 deletions compat/src/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,13 @@ options.vnode = vnode => {
let type = vnode.type;
let props = vnode.props;

// Alias `class` prop to `className` if available
if (props.class != props.className) {
classNameDescriptor.enumerable = 'className' in props;
if (props.className) props.class = props.className;
Object.defineProperty(props, 'className', classNameDescriptor);
}

// Apply DOM VNode compat
if (typeof type != 'function') {
// Apply defaultValue to value
Expand Down Expand Up @@ -117,13 +124,6 @@ options.vnode = vnode => {
}
}

// Alias `class` prop to `className` if available
if (props.class || props.className) {
classNameDescriptor.enumerable = 'className' in props;
if (props.className) props.class = props.className;
Object.defineProperty(props, 'className', classNameDescriptor);
}

// Events
applyEventNormalization(vnode);

Expand Down
58 changes: 57 additions & 1 deletion compat/test/browser/render.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { createElement, render } from 'preact/compat';
import React, { createElement, render, Component } from 'preact/compat';
import { setupRerender } from 'preact/test-utils';
import {
setupScratch,
teardown,
Expand All @@ -9,11 +10,15 @@ describe('compat render', () => {
/** @type {HTMLDivElement} */
let scratch;

/** @type {() => void} */
let rerender;

const ce = type => document.createElement(type);
const text = text => document.createTextNode(text);

beforeEach(() => {
scratch = setupScratch();
rerender = setupRerender();
});

afterEach(() => {
Expand Down Expand Up @@ -140,4 +145,55 @@ describe('compat render', () => {
render(<Foo className="foo" />, scratch);
expect(scratch.firstChild.className).to.equal('foo');
});

// Issue #2275
it('should normalize class+className + DOM properties', () => {
function Foo(props) {
return <ul {...props} class="old" />;
}

render(<Foo fontSize="xlarge" className="new" />, scratch);
expect(scratch.firstChild.className).to.equal('new');
});

// Issue #2224
it('should not mark both class and className as enumerable', () => {
function ClassNameCheck(props) {
return (
<div>{props.propertyIsEnumerable('className') ? 'Failed' : ''}</div>
);
}

let update;
class OtherThing extends Component {
render({ children }) {
update = () => this.forceUpdate();
return (
<div>
{children}
<ClassNameCheck class="test" />
</div>
);
}
}

function App() {
return (
<OtherThing>
<ClassNameCheck class="test" />
</OtherThing>
);
}

render(<App />, scratch);

update();
rerender();

console.log(scratch.textContent);
expect(/Failed/g.test(scratch.textContent)).to.equal(
false,
'not enumerable'
);
});
});
2 changes: 1 addition & 1 deletion hooks/src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ type Ref<T> = { current: T };
* Note that `useRef()` is useful for more than the `ref` attribute. It’s handy for keeping any mutable
* value around similar to how you’d use instance fields in classes.
*/
export function useRef<T>(initialValue: T): Ref<T>;
export function useRef<T>(initialValue: T | null): Ref<T>;

/**
* `useRef` without an initial value is the special case handling `ref` props.
Expand Down

0 comments on commit eca2cf2

Please sign in to comment.