Skip to content

Revert "Merge pull request #1293 from reactjs/feature/add-option-to-replace-null-updated" #1300

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,4 @@ Naming/RescuedExceptionsVariableName:

Metrics/BlockLength:
Exclude:
- 'test/**/*_test.rb'
- 'test/**/*_test.rb'
26 changes: 2 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,13 @@ Read the [full review here](https://clutch.co/profile/shakacode#reviews?sort_by=
- [Upgrading](#upgrading)
- [2.7 to 3.0](#27-to-30)
- [2.3 to 2.4](#23-to-24)
- [Other features](#other-features)
- [Replace `null` with `undefined` in props](#replace-null-with-undefined-in-props)
- [Common Errors](#common-errors)
- [Getting warning for `Can't resolve 'react-dom/client'` in React < 18](#getting-warning-for-cant-resolve-react-domclient-in-react--18)
- [Undefined Set](#undefined-set)
- [Using TheRubyRacer](#using-therubyracer)
- [HMR](#hmr)
- [Related Projects](#related-projects)
- [Contributing](#contributing)
- [Supporters](#supporters)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

Expand Down Expand Up @@ -531,6 +528,7 @@ use it like so:
ReactUJS.getConstructor = ReactUJS.constructorFromRequireContext(require.context('components', true));
```


## Server-Side Rendering

You can render React components inside your Rails server with `prerender: true`:
Expand Down Expand Up @@ -803,26 +801,6 @@ For the vast majority of cases this will get you most of the migration:
- add `import PropTypes from 'prop-types'` (Webpacker only)
- re-run `bundle exec rails webpacker:install:react` to update npm packages (Webpacker only)

## Other features

### Replace `null` with `undefined` in props

React-Rails converts `nil` to `null` while parsing props from Ruby to JavaScript. Optionally, you can configure React-Rails to parse `nil` values to `undefined` as per the following:

```ruby
# config/application.rb
module TheAppName
class Application < Rails::Application
# ...
# Set to true to convert null values in props into undefined
config.react.null_to_undefined_props = true
# ...
end
end
```

More information in: [discussion#1272](https://github.com/reactjs/react-rails/discussions/1272).

## Common Errors
### Getting warning for `Can't resolve 'react-dom/client'` in React < 18

Expand Down Expand Up @@ -879,7 +857,7 @@ By contributing to React-Rails, you agree to abide by the [code of conduct](http

You can always help by submitting patches or triaging issues. Even offering reproduction steps to issues is incredibly helpful!

## Supporters
# Supporters

The following companies support the development of this and other open-source projects maintained by ShakaCode by providing licenses to the ShakaCode team. ShakaCode stands by the usefulness of these products!

Expand Down
16 changes: 1 addition & 15 deletions lib/react/rails/component_mount.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,7 @@ def generate_html_options(name, options, props, prerender_options)
unless prerender_options == :static
html_options[:data].tap do |data|
data[:react_class] = name
data[:react_props] = props_to_json(
props,
null_to_undefined: Dummy::Application.config.react.null_to_undefined_props
)
data[:react_props] = (props.is_a?(String) ? props : props.to_json)
data[:hydrate] = "t" if prerender_options

num_components = @cache_ids.count { |c| c.start_with? name }
Expand All @@ -70,17 +67,6 @@ def generate_html_options(name, options, props, prerender_options)
html_options
end

def props_to_json(props, options = { null_to_undefined: false })
return props if props.is_a?(String)
return props.to_json unless options[:null_to_undefined]

# This regex matches key:value with null values while ensuing no string with similar
# pattern gets matched. It doesn't include null values in arrays.
props.to_json
.gsub(/([^\\]":)null([,}\]])/, '\1undefined\2') # match simple null values
.gsub(/([^\\]":(\[[^\\"]+,|\[))null([,\]])/, '\1undefined\3') # Match nulls in array
end

def rendered_tag(html_options, &block)
html_tag = html_options[:tag] || :div

Expand Down
1 change: 0 additions & 1 deletion lib/react/rails/railtie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ class Railtie < ::Rails::Railtie
config.react.jsx_transformer_class = nil # defaults to BabelTransformer
config.react.camelize_props = false # pass in an underscored hash but get a camelized hash
config.react.sprockets_strategy = nil # how to attach JSX to the asset pipeline (or `false` for none)
config.react.null_to_undefined_props = false # Set to true to convert null values in props into undefined

# Server rendering:
config.react.server_renderer_pool_size = 1 # increase if you're on JRuby
Expand Down
88 changes: 0 additions & 88 deletions test/react/rails/component_mount_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

require "test_helper"

# rubocop:disable Metrics/ClassLength
class ComponentMountTest < ActionDispatch::IntegrationTest
module DummyRenderer
def self.render(component_name, props, _prerender_options)
Expand Down Expand Up @@ -129,92 +128,5 @@ def self.react_rails_prerenderer

assert_equal %(<div>rendered Foo with {&quot;ok&quot;:true}</div>), rendered_component
end

test "#react_component sets null props to undefined when null_to_undefined_props set to true" do
app.config.react.null_to_undefined_props = true

@helper.setup(DummyController)
rendered_component = @helper.react_component("Foo", { bar: nil, content: 'bar":null,' })

assert_includes rendered_component, '&quot;bar&quot;:undefined,&quot;content&quot;:&quot;bar\\&quot;:null,&quot;'
end

test "#react_component passes null props as null when null_to_undefined_props set to false" do
app.config.react.null_to_undefined_props = false

@helper.setup(DummyController)
rendered_component = @helper.react_component("Foo", { bar: nil, content: 'bar":null,' })

assert_includes rendered_component, "&quot;bar&quot;:null,&quot;content&quot;:&quot;bar\\&quot;:null,&quot;"
end

test "#props_to_json doesn't converts null values to undefined be default" do
props = { name: nil }
expected_json = '{"name":null}'
component_mount = React::Rails::ComponentMount.new

actual_json = component_mount.send(:props_to_json, props)

assert_equal(expected_json, actual_json)
end

test "#props_to_json converts null values to undefined with null_to_undefined: true option" do
props = { bar: nil, content: 'bar":null,' }
expected_json = '{"bar":undefined,"content":"bar\\":null,"}'
component_mount = React::Rails::ComponentMount.new

actual_json = component_mount.send(:props_to_json, props, { null_to_undefined: true })

assert_equal(expected_json, actual_json)
end

test "#props_to_json converts null values in arrays to undefined with null_to_undefined: true option" do
props = { items1: [nil], items2: [1, nil], items3: [nil, 1], items4: [1, nil, 2] }
expected_json = '{"items1":[undefined],"items2":[1,undefined],"items3":[undefined,1],"items4":[1,undefined,2]}'
component_mount = React::Rails::ComponentMount.new

actual_json = component_mount.send(:props_to_json, props, { null_to_undefined: true })

assert_equal(expected_json, actual_json)
end

test "#props_to_json doesnt converts null-like values in arrays to undefined with null_to_undefined: true option" do
props = {
items1: "[null]",
items2: "[1,null]",
items3: "[null,1]",
items4: "[1,null,2]",
items5: '["a",null]',
items6: '[null,"b"]',
items7: '["a",null,"b"]',
items8: '["a",nullx,"b"]'
}
expected_json = '{"items1":"[null]","items2":"[1,null]","items3":"[null,1]","items4":"[1,null,2]",' \
'"items5":"[\"a\",null]","items6":"[null,\"b\"]","items7":"[\"a\",null,\"b\"]"' \
',"items8":"[\"a\",nullx,\"b\"]"}'
component_mount = React::Rails::ComponentMount.new

actual_json = component_mount.send(:props_to_json, props, { null_to_undefined: true })

assert_equal(expected_json, actual_json)
end

test "#props_to_json doesnt converts null values in nested arrays to undefined with null_to_undefined: true" do
props = {
items1: nil,
items2: [1, nil, 2],
items3: nil,
items4: "[1, null, 2]",
items5: nil
}
expected_json = '{"items1":undefined,"items2":[1,undefined,2],"items3":undefined,"items4":"[1, null, 2]"' \
',"items5":undefined}'
component_mount = React::Rails::ComponentMount.new

actual_json = component_mount.send(:props_to_json, props, { null_to_undefined: true })

assert_equal(expected_json, actual_json)
end
end
end
# rubocop:enable Metrics/ClassLength